Swift3转Swift4报错:无法将'(_)->()'转为'((Bool, Error?) -> Void)?'
解决Swift 3→Swift 4迁移中savePhoto函数的闭包类型不匹配错误
嘿,我来帮你搞定这个Swift迁移的坑!你遇到的这个错误本质是闭包参数类型不兼容,具体原因和解决方法我给你拆解清楚:
错误根源
你在调用AVCaptureStillImageOutput的captureStillImageAsynchronously(from:completionHandler:)方法时,传入的completion闭包类型和系统方法要求的不匹配:
- Swift 4里这个方法的完成闭包要求接收两个参数:
(Bool, Error?) -> Void(一个布尔值表示操作成功与否,一个可选错误对象) - 但你的
takePhoto方法定义的completion是无参的(() -> Void)?,直接传进去就会触发类型转换失败的报错。
两种解决方案
方案1:修改takePhoto的接口(推荐,更贴合Swift 4的API设计)
直接把takePhoto的completion参数类型改成和系统方法一致,这样后续调用也能拿到操作结果:
func takePhoto(_ previewLayer: AVCaptureVideoPreviewLayer, location: CLLocation?, completion: ((Bool, Error?) -> Void)? = nil) { guard let connection = stillImageOutput?.connection(with: AVMediaType.video) else { completion?(false, NSError(domain: "YourDomain", code: -1, userInfo: [NSLocalizedDescriptionKey: "Failed to get capture connection"])) return } connection.videoOrientation = Helper.videoOrientation() // 后续调用系统方法时,直接传completion即可 stillImageOutput?.captureStillImageAsynchronously(from: connection, completionHandler: completion) }
方案2:保留原接口,做闭包适配(适合不想改动原有调用逻辑的场景)
如果你不想修改takePhoto的外部接口,可以在调用系统方法的地方加一层闭包包装,把系统返回的参数处理后再调用原有的无参completion:
func takePhoto(_ previewLayer: AVCaptureVideoPreviewLayer, location: CLLocation?, completion: (() -> Void)? = nil) { guard let connection = stillImageOutput?.connection(with: AVMediaType.video) else { completion?() return } connection.videoOrientation = Helper.videoOrientation() stillImageOutput?.captureStillImageAsynchronously(from: connection) { [weak self] imageDataSampleBuffer, error in // 这里可以添加你自己的图片保存逻辑(比如把sample buffer转成UIImage、写入相册等) // ... // 调用原来的无参completion completion?() } }
迁移小提示
Swift 3到Swift 4的API调整不少,尤其是AVFoundation、CoreLocation这类框架,很多闭包的参数做了更严谨的定义。遇到这类类型不匹配的错误,直接Option+点击方法名查看系统API的Swift 4定义,对比原来的Swift 3版本,就能快速定位问题~
内容的提问来源于stack exchange,提问作者Lander Saavedra
相关产品推荐
相关产品推荐

