在类A中使用类B定义的AVCapturePhotoCaptureDelegate未被调用问题
问题:AVCapturePhotoCaptureDelegate协议方法无法触发
我现在有一个遵循AVCapturePhotoCaptureDelegate协议的类B,代理在B的初始化阶段完成设置,但在类A中使用这个代理时,协议方法始终无法被调用。示例代码如下:
class A { private var photoOutput = AVCapturePhotoOutput() @objc func captureFrame() { ... let b = B(a: self) photoOutput.capturePhoto(with: photoSettings, delegate: b) } func somemethod() { ... } } class B: AVCapturePhotoCaptureDelegate { weak var a: A? weak var delegate: AVCapturePhotoCaptureDelegate? init(a: A) { self.a = a super.init() self.delegate = self } // 这个方法始终不会被调用... func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) { print("Delegate method called") a?.somemethod() } }
我这么做是因为captureFrame方法可能会被循环调用,需要持久化传入的参数以避免竞态条件。我可能误解了这种实现方式的工作原理,此外我还尝试直接传入代理变量,例如:
photoOutput.capturePhoto(with: photoSettings, delegate: b.delegate)
但问题依然存在。
原因与解决办法
核心问题:代理对象被提前释放
在captureFrame方法中,你创建的B实例是局部变量,方法执行完毕后就会被ARC自动释放。而AVCapturePhotoOutput的capturePhoto(with:delegate:)方法对代理对象的引用是弱引用,不会持有它,所以当方法执行完,B实例已经被销毁,自然无法触发协议方法。
另外,你在B类中额外声明的weak var delegate: AVCapturePhotoCaptureDelegate?完全是多余的——B本身已经遵循了协议,直接用B实例作为代理即可,不需要多此一举。
修复步骤
- 在类A中添加成员变量持有B实例,避免它被提前释放:
class A { private var photoOutput = AVCapturePhotoOutput() // 添加变量持有B实例,防止被提前释放 private var photoDelegate: B? @objc func captureFrame() { ... let b = B(a: self) photoDelegate = b photoOutput.capturePhoto(with: photoSettings, delegate: b) } func somemethod() { ... } }
- 简化B类,移除多余的
delegate属性:
class B: AVCapturePhotoCaptureDelegate { weak var a: A? init(a: A) { self.a = a super.init() } func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) { print("Delegate method called") a?.somemethod() // 回调完成后可手动置空代理实例,避免不必要的内存占用 (a as? A)?.photoDelegate = nil } }
补充说明
如果captureFrame会被频繁调用,每次调用都需要创建新的B实例,那么在协议方法回调完成后,记得手动将photoDelegate置空,避免内存浪费。同时,由于a是弱引用,不会产生循环引用问题。
内容的提问来源于stack exchange,提问作者DanielK
相关产品推荐
相关产品推荐

