完成块在 Swift 3 中变为 nil

Posted

技术标签:

【中文标题】完成块在 Swift 3 中变为 nil【英文标题】:Completion Block becomes nil in Swift 3 【发布时间】:2017-06-21 08:52:36 【问题描述】:

我检查了similar question,但在我的情况下出现的问题完全不同。

我使用typealias 来避免重写类似的完成块声明。

typealias FetchFilesCompletionBlock = ( _ files: OPFiles?, _ error: Error?) -> Void

在函数定义中,我使用了FetchFilesCompletionBlock的可选类型。即使使用完成块调用函数,在函数体中 onCompletion 变为 nil。

func fetchFile(_ param: [String: String]? = nil, onCompletion: FetchFilesCompletionBlock?) 
  // I found onCompletion is nil here.
  // function body

fetchFile(_: onCompletion:) 调用如下:

let onCompletion =  (files, error) in
  DispatchQueue.main.async(execute: [weak self]() in
    self?.onCompletion(files, error: error)
  )
 as? FetchFilesCompletionBlock
// Here also I found that onCompletion is nil
dataManager.fetchFile(param, onCompletion: onCompletion)

如果我从上面的 sn-p 中删除 as? FetchFilesCompletionBlock,我会得到一个编译时错误 Cannot convert value of type '(OPFiles?, NSError?) -> ()' to expected argument type 'FetchFilesCompletionBlock?'

【问题讨论】:

【参考方案1】:

问题是您忘记指定onCompletion 的类型。通过onCompletion 的声明,您还需要指定其类型为FetchFilesCompletionBlock

let onCompletion: FetchFilesCompletionBlock = (file, error) in
    //Your code

dataManager.fetchFile(param, onCompletion: onCompletion)

【讨论】:

感谢@Nirav,它运作良好。能说说背后的原因吗? @MilanKamilya 欢迎朋友 :),我已经写过您没有在声明中指定 onCompletion 的类型,这就是问题所在。 你能告诉我as? FetchFilesCompletionBlocklet onCompletion: FetchFilesCompletionBlock有什么区别 @MilanKamilya 带块的类型转换永远不会起作用,所以as? FetchFilesCompletionBlock 总是会失败【参考方案2】:

问题是,在块定义中,您使用 Error 作为错误的类,但在您创建的块中,您使用 NSError 代替,虽然它们是兼容的,但它们不是“隐式”强制转换的,并且按照 Nirav 建议的方式执行“显式地" 铸造了差异(NSError 到 Error)

【讨论】:

没错。感谢@HusseinDimessi 进行深入检查。 let onCompletion = (files: OPFiles?, error: Error?) in - 也出于同样的原因解决了这个问题。 只删除Errors末尾的s?在这里;)但是是的,出于同样的原因,这将解决它

以上是关于完成块在 Swift 3 中变为 nil的主要内容,如果未能解决你的问题,请参考以下文章

在 Swift 3 中使用 prepareForSegue 分配对象变为 nil

变量在完成处理程序之外变为 nil [重复]

从 swift 评估 javascript 函数,在完成处理程序中得到 nil

如何表示 nil Error Swift 完成块

Swift Modal Self 变为 Nil

Swift:UIPopoverPresentationControllerDelegate 委托变为 nil