【发布时间】:2015-07-01 14:39:16
【问题描述】:
我一直在努力让自己熟悉 Swift,但我最近遇到了一个涉及可选绑定和在闭包上下文中捕获引用的特殊问题。
鉴于以下声明(为清楚起见,代码已缩写;完整代码在末尾提供):
class Thing
{
func giveNameIfSize() -> String? {
/.../
}
}
typealias IterationBlock = (Thing) -> Bool
class Iterable
{
func iterate(block: IterationBlock) {
/.../
}
}
Iterable 对象可以存储Things 的集合,并且可以使用闭包遍历它们。现在假设我们要查找设置了size 属性的Thing 对象的名称。我们可以这样做:
var name: String?
iterable.iterate { (someThing) -> Bool in
/*
Assigning the result of the giveNameIfSize() function to
a variable 'name' declared outside of the closure and
captured by reference
*/
if name = someThing.giveNameIfSize() {
return true
}
return false
}
但是,上面的代码会产生以下编译错误:
无法分配给“字符串”类型的不可变值?
奇怪的是,当我们在可选绑定中使用另一个变量时,问题就消失了:
iterable.iterate { (someThing) -> Bool in
if var tempResult = someThing.giveNameIfSize() {
name = tempResult
return true
}
return false
} /* COMPILES AND RUNS */
如果我们在可选绑定之外为外部声明的变量name赋值,问题也解决了:
iterable.iterate { (someThing) -> Bool in
name = someThing.giveNameIfSize()
if name != nil {
return true
}
return false
} /* ALSO COMPILES AND RUNS */
完整源代码here.
Obs.:使用 Swift 1.2 而非 2.0 测试此代码。
====
这是一个错误吗?还是我错过了什么?
【问题讨论】: