Swift闭包存储并作为变量访问

6

我希望在Swift项目中实现回调,就像我以前在Objective-C中做的那样。 我需要一个闭包类型的变量。该闭包应该以一个对象作为参数,并返回空值。

var downloadCompleted: (MLBook) -> (Void)!

当需要触发回调时,我会这样做:
if self.downloadCompleted {
   self.downloadCompleted(book)
}

编译器会报错并显示以下信息:
 Type '(MLBook) -> (Void)!' does not conform to protocol 'BooleanType'

如果我去掉if语句,编译器会报错:

Property 'self.downloadCompleted' not initialized

即使它是隐式解包,也要小心使用。
当我尝试获取回调函数时:
BookStore.sharedInstance.downloadCompleted{(book: MLBook) -> () in
   println("Print if you got the callback")
}

我收到了这个错误信息:
'(MLBook) -> ()' is not convertible to 'MLBook'

我更担心最后的错误信息,因为我不太确定它想告诉我什么。

如果有帮助,将不胜感激。谢谢

2个回答

9
以下是您的示例代码。您有许多错误,这些错误在附图中有所说明。请注意,我让 download() 方法返回 Bool,以便可以在此屏幕截图中查看结果。
但是,您错误地使用了隐式解包可选项(也称为“!”)。当值可能为 nil 但将在已知时间分配且不更改时,才会使用此类可选项(请参见 Apple 文档的描述)。您的 downloadCompleted 是一个真正的可选项(至少在您的示例中用途如此)。因此,更好的代码,事实证明略微简单,如下所示:

5

2个错误。首先,整个类型应该包裹在()中,然后跟随一个?或!作为可选项或隐式展开的可选项。其次,在Swift中,您应该检查nil,没有隐式布尔转换。

在您的用例中,您应该使用Optional而不是隐式展开的可选项。因为你的属性很有可能具有nil值。通过IUO(隐式展开的可选项),您可以跳过编译器警告并得到运行时错误。

import Foundation

class MLBook {
    var name = "name"
}

class A {
    var downloadCompleted: ((MLBook) -> Void)?

    func down(){
        var book = MLBook()
        if let cb = self.downloadCompleted {
            cb(book)
        }
    }  
}

var a = A()
a.downloadCompleted = {
    (book: MLBook) -> Void in
    println(book.name)
}

a.down()

谢谢。那很有道理。但是当我尝试获取回调时,会出现错误:Cannot invoke 'println' with an argument of type '(MLBook) -> Void'。我相当确定我没有正确调用它。你认为这是为什么? - alex
我猜你错过了将闭包分配给属性的“=”符号。 - Shuo

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