代码之家  ›  专栏  ›  技术社区  ›  Mukesh

swift:在初始化之前由闭包捕获的常量[duplicate]

  •  1
  • Mukesh  · 技术社区  · 5 年前

    下一堂课

    class Foo {
       let _defaultValue = "N/A"
       let value: String 
    
       init (dict: NSDictionary) {
           self.value = dict["bar"] as? String! ?? _defaultValue
       }
    }
    

    编译失败,并显示消息 constant 'self.value' captured by a closure before being initialized

    就我所见,没有操作符读 self.value 这个信息真的很让人困惑。

    我随机发明的解决方法让我更加困惑:

    class Foo {
           let value: String 
    
           init (dict: NSDictionary) {
               let _defaultValue = "N/A"
               self.value = dict["bar"] as? String! ?? _defaultValue
           }
        }
    

    制作 _defaultValue 在构造函数内部声明和初始化关闭编译器投诉和程序工作!

    怎么解释这件事?

    0 回复  |  直到 5 年前
        1
  •  13
  •   Martin R    5 年前

    错误消息的原因是nil合并运算符 定义为

    public func ??<T>(optional: T?, defaultValue: @autoclosure () throws -> T) rethrows -> T
    

    对第二个参数执行“自动闭包”(以便 短路行为)。所以

    self.value = dict["bar"] as? String ?? _defaultValue
    

    由编译器转换为

    self.value = dict["bar"] as? String ?? { self._defaultValue }()
    

    编译器在这里抱怨是因为 self 以前被抓过 完全初始化。(错误消息略有不同 在SWIFT 2和SWIFT 3之间)。

    可能的解决办法。 您可以先将属性分配给局部变量:

    init(dict: NSDictionary){
        let defValue = _defaultValue
        self.value = dict["bar"] as? String! ?? defValue
    }
    

    或者可以使它成为类的静态属性:

    class Foo {
        static let _defaultValue = "N/A"
        let value: String
    
        init(dict: NSDictionary) {
            self.value = dict["bar"] as? String ?? Foo._defaultValue
        }
    }
    

    或替换 ?? 通过if语句:

    class Foo {
        let _defaultValue = "N/A"
        let value: String
    
        init (dict: NSDictionary) {
            if let value = dict["bar"] as? String {
                self.value = value
            } else {
                self.value = _defaultValue
            }
        }
    }
    

    补遗: 相关资源:

    引用错误报告:

    jordan rose:这是真的,因为&是使用@autoclosure实现的,但肯定不是最佳的。