AVCaptureFileOutputRecordingDelegate代理传递录制URL为nil问题排查
问题分析与修复方案
首先,先揪出最可能的问题——你在代理方法里用错了URL参数!
看你的代码:
urlDelegate?.URL = outputURL
但代理方法的参数明明是outputFileURL啊!你这里写的outputURL应该是你自己定义的某个类变量,但这个变量大概率没有在录制过程中被正确赋值,所以才会是nil。而系统通过代理方法传递给你的、真正的录制完成后的文件URL是outputFileURL,这才是你应该用的那个!
第一步:修正参数错误
把代码改成直接使用代理方法传入的outputFileURL:
func capture(_ output: AVCaptureFileOutput!, didFinishRecordingToOutputFileAt outputFileURL: URL!, fromConnections connections: [Any]!, error: Error!) { guard error == nil else { // 处理录制错误 print("录制出错:\(error!)") return } // 这里改用参数里的outputFileURL urlDelegate?.URL = outputFileURL }
第二步:检查urlDelegate的生命周期
如果改了参数之后还是nil,那大概率是urlDelegate本身为nil了,常见原因有两个:
urlDelegate被声明为weak var,但持有它的对象已经被提前释放(比如你在某个ViewController里设置了delegate,但这个VC在录制完成前就被销毁了)- 你根本没有正确给
urlDelegate赋值,比如忘记调用cameraObject.urlDelegate = self这类代码
可以在代理方法里加个打印验证:
func capture(_ output: AVCaptureFileOutput!, didFinishRecordingToOutputFileAt outputFileURL: URL!, fromConnections connections: [Any]!, error: Error!) { guard error == nil else { print("录制出错:\(error!)") return } print("outputFileURL: \(outputFileURL)") print("urlDelegate是否为nil:\(urlDelegate == nil)") urlDelegate?.URL = outputFileURL }
如果打印出urlDelegate是否为nil:true,那就要去检查你的delegate对象是否还存活,以及赋值逻辑是否正确。
关于“录制是否完成”的疑问
你不用担心——只要didFinishRecordingToOutputFileAt被调用且error为nil,就说明视频录制已经完全完成,文件已经成功写入到outputFileURL对应的路径了。这个方法就是AVCapture框架用来通知你录制结束的回调,不存在“录制未完成”的情况,你之前的困惑应该是因为用错了URL参数导致的错觉。
额外优化建议
如果delegate模式用着别扭,也可以考虑用闭包来传递结果,代码会更简洁直观:
// 在你的相机类里定义一个闭包属性 var onRecordingCompleted: ((URL?) -> Void)? // 代理方法里调用闭包 func capture(_ output: AVCaptureFileOutput!, didFinishRecordingToOutputFileAt outputFileURL: URL!, fromConnections connections: [Any]!, error: Error!) { if error == nil { onRecordingCompleted?(outputFileURL) } else { onRecordingCompleted?(nil) } } // 使用的时候直接设置闭包 cameraObject.onRecordingCompleted = { url in if let url = url { // 处理录制完成的URL } else { // 处理错误 } }
内容的提问来源于stack exchange,提问作者dre_84w934
相关产品推荐
相关产品推荐

