在iOS中,Objective-C中的Block和Swift中的Closure有什么区别?

49
在教程中,它们都被描述为功能上相同的,即使闭包比块更容易,它也避免了块和内存管理的复杂性。我已经看过很多教程,但除了这些内容,我还没有理解 Swift 的“闭包”和 Objective-C 的“块”之间的区别。

在StackOverflow上,使用“勾选标记”来标记答案是预期的行为。如果提供的答案不能满足您的需求,请在答案下方留下评论。 - GoZoner
3个回答

74

摘自:苹果公司“使用Swift与Cocoa和Objective-C。”iBooks:

“Swift闭包和Objective-C块是兼容的,因此您可以将Swift闭包传递给期望块的Objective-C方法。 Swift闭包和函数具有相同的类型,因此甚至可以传递Swift函数的名称。

闭包具有类似于块的捕获语义,但在一个关键方面不同:变量是可变的而不是被复制的。 换句话说,在Swift中,变量的默认行为是Objective-C中__block的行为。”


@GoZoner,您能否举个例子详细说明第二个声明吗? - Ashok
作为一种优化,如果一个值在闭包中没有被改变,并且在闭包创建后也没有被改变,Swift 可能会捕获并存储该值的副本。 - RY_ Zheng

5

略有不同之处。其中一个被提到过;变量被作为变量而不是值来捕获。这既可以是有用的,也可能是陷阱。重要的是,在 Swift 闭包中可以定义一个捕获列表,如果在捕获列表中包含 self.property,则该属性的值会被捕获,而不是 self。这也简化了捕获弱变量的过程。


3
为了展示不同之处,这里给出一个实际的代码示例:
下面的代码是可以编译通过的:
let x : @convention(swift) (inout Int) -> ()

这并不包括以下内容:
let y : @convention(block) (inout Int) -> ()

出现错误:(inout Int) -> () 在Objective-C中无法表示。


1
你不能使用inout,因为Objective-C调用约定没有引用,并且引用和指针之间的转换不是隐式的。但它确实有指针,所以你必须使用UnsafePointer<Int>。这使得这两个签名是一样的。 - Brandon
@Brandon 正如之前所说,如果你确信块和闭包是相同的,请写信给 Swift 开发人员,告诉他们应该更改语言文档,因为你认为它是错误的 ;) - Kametrixom
@Brandon,1小时前:“块和闭包是相同的”[来源](http://stackoverflow.com/questions/38285689/in-swift-can-a-function-be-a-type/38285902#comment63991399_38285902);“[...]这并不意味着它[a block]不是一个闭包。”[来源](http://stackoverflow.com/questions/38285689/in-swift-can-a-function-be-a-type/38285902#comment63991786_38285902)。 “Swift中的闭包类似于C和Objective-C中的块”,[Swift文档来源](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html#//apple_ref/doc/uid/TP40014097-CH11-ID94) - Kametrixom
@Brandon 在同一页上还有这样一句话:“在函数中引入的全局和嵌套函数实际上是闭包的特例。”而你说:“函数根本不是闭包的一种特殊类型” [来源](http://stackoverflow.com/questions/38285689/in-swift-can-a-function-be-a-type/38285902#comment63991444_38285902) - Kametrixom
哈哈..我的陈述只是强调了您从Swift文档中读到的内容。它们不仅相似,而且完全相同。它们都是“NSBlock”。因此,请再告诉我我哪里错了。按定义,函数和闭包是完全一样的(维基百科)。但是,汇编代码并非如此。它们的实现方式不同。使用“Invoke”调用闭包。通过将参数推送到寄存器和堆栈中直接调用函数。闭包通过objc_msgSend调用,在运行时动态地将参数推送到堆栈上。如果您不知道更好的方法,请保持安静。 - Brandon
显示剩余2条评论

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