Swift嵌套函数 vs 闭包变量

5

我想创建一个函数,从CloudKit获取记录,如果遇到临时网络错误,则应该重试。

func fetchRecord(withRecordID recordID: CKRecordID, returnBlock: (optError: ErrorType?) -> Void){

    func internalReturnBlock(optError optError: ErrorType?){
        if NSThread.isMainThread() {
            returnBlock(optError: optError)
        }
        else{
            dispatch_async(dispatch_get_main_queue(), { 
                returnBlock(optError: optError)
            })
        }
    }

    func internalWork(){
        privateDB.fetchRecordWithID(recordID) { (optRecord, optError) in
            if let error = optError{
                // IF NETWORK ERROR RETRY
                internalWork()
            }
            else{
                internalReturnBlock(optError: nil)
            }
        }
    }

    internalWork()
}

这里我定义了一个函数(简化版),如果fetch遇到错误,它会通过调用嵌套函数internalWork()来重试。

我的问题是使用嵌套函数和创建本地闭包变量之间有什么区别? 例如,在这里,我将internalReturnBlock更改为闭包变量:

func fetchRecord2(withRecordID recordID: CKRecordID, returnBlock: (optError: ErrorType?) -> Void){

    var internalReturnBlock = { (optError: NSError?) in
        if NSThread.isMainThread() {
            returnBlock(optError: optError)
        }
        else{
            dispatch_async(dispatch_get_main_queue(), {
                returnBlock(optError: optError)
            })
        }
    }

    func internalWork(){
        privateDB.fetchRecordWithID(recordID) { (optRecord, optError) in
            if let error = optError{
                // IF NETWORK ERROR RETRY
                internalWork()
            }
            else{
                internalReturnBlock(nil)
            }
        }
    }


    internalWork()
}

使用嵌套函数和变量块有何区别?有什么优点或问题?
1个回答

10

效果上没有区别。一个是有名字的声明函数,另一个是匿名函数。但它们都是函数。在 Swift 中,函数是闭包,所以它们都是闭包。

允许匿名函数使用一些形式的缩写,例如省略单行代码中返回值的 return。但是这些缩写都不会产生任何最终有效的区别。

然而,在 Swift 中,匿名函数有一个声明函数所没有的特点 — 捕获列表。这可以帮助避免保留周期。

f {
    [unowned self] in
    return self.name
} 

此外,在将匿名函数作为参数的函数声明之后定义了该匿名函数,因此它可以使用在该声明中出现的术语:

f(param:String) {
    return param
}

但如果您没有使用这些功能,那么你使用哪个并不重要。它们的工作方式是相同的。


2
阅读我的书可能会对你有所帮助:http://www.apeth.com/swiftBook/ch02.html#_anonymous_functions 请注意,我从声明函数转向匿名函数的动机基本上只是因为名称是不必要的。 - matt
感谢您详细的回答!我也刚刚发现闭包变量不能以我声明的方式调用自身,所以internalWork()必须保持为嵌套函数。 - the Reverend
好观点!有绕过这个限制的方法;然而,我不确定你的递归是否是一个好主意。如果我们永远无法通过怎么办?最终你会遇到真正的堆栈溢出问题。 - matt
是的,你说得对,递归必须有一个重试限制。 :) - the Reverend

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接