swift2 什么原因导致“初始化前由闭包捕获的常量”错误

yrdbyhpb  于 2022-11-06  发布在  Swift
关注(0)|答案(1)|浏览(197)

在下面的类中

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并在构造函数中对其进行初始化可使代码编译。
如果有人能解释为什么在第一种情况下会发生错误,以及在第二种情况下编译器会更高兴,那将是一个巨大的帮助。

2guxujil

2guxujil1#

出现该错误消息的原因是nil-coalescing运算符定义为

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
        }
    }
}

引用错误报告中的话:
乔丹·罗斯:这是真的,因为&&是使用@ autoclosures实现的,但它肯定不是最优的。

相关问题