【问题标题】:Optional Binding, Capturing References and Closures [possible bug]可选绑定、捕获引用和闭包 [可能的错误]
【发布时间】: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 测试此代码。

====

这是一个错误吗?还是我错过了什么?

【问题讨论】:

    标签: swift closures optional


    【解决方案1】:

    您收到的错误有点误导,但这里的根本问题是您正在尝试做 Swift 不支持的事情。在 Swift 中,你不能在条件中使用赋值的结果。

    话虽如此,您提出的两种替代方法都可以使用,尽管我倾向于认为这两种方法中的第一种更 Swifty。

    【讨论】:

    • 我明白你的意思,你是对的。该错误消息与闭包无关,而与 if 语句本身有关。但是,从if var tempResult = someThing.giveNameIfSize() { 有效的事实来看,是否可以假设可选绑定被优化为不同于评估赋值的if 语句?
    猜你喜欢
    • 2011-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-05
    • 1970-01-01
    • 2020-12-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多