我一直在努力让自己熟悉Swift,但最近我遇到了这个涉及Optional Bindings的特殊问题,并在Closures的上下文中捕获了引用。
给出以下声明(为了清楚起见,缩写为代码;在末尾提供完整代码):
class Thing
{
func giveNameIfSize() -> String? {
/.../
}
}
typealias IterationBlock = (Thing) -> Bool
class Iterable
{
func iterate(block: IterationBlock) {
/.../
}
}
Iterable
对象可以存储Things
的集合,并可以使用闭包迭代它们。现在说我们想要找到Thing
属性设置的size
对象的名称。我们可以这样做:
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
}
但是,上面的代码会生成以下编译器错误:
无法分配“String?”类型的不可变值
奇怪的是,当我们在可选绑定中使用另一个变量时,问题就消失了:
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。
====
这是一个错误吗?或者我错过了什么?
答案 0 :(得分:1)
您收到的错误有点误导,但这里的根本问题是您正在尝试做一些Swift不支持的事情。在Swift中,您无法在条件中使用赋值结果。
话虽如此,你提出的两种替代方法都会奏效,虽然我倾向于认为两者中的第一种方法更加宽松。