What causes 'Constant captured by a closure before being initialized' error

前端 未结 1 1566
难免孤独
难免孤独 2020-12-02 00:13

In a following class

class Foo {
   let _defaultValue = \"N/A\"
   let value: String 

   init (dict: NSDictionary) {
       self.value = dict[\"bar\"] as? S         


        
相关标签:
1条回答
  • 2020-12-02 00:51

    The reason for the error message is that the nil-coalescing operator is defined as

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

    and does a "auto closure" on the second argument (in order to get a short-circuiting behaviour). So

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

    is transformed by the compiler to

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

    and here the compiler complains because self is captured before being fully initialised. (The error messages are slightly different between Swift 2 and Swift 3).

    Possible workarounds. You can assign the property to a local variable first:

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

    Or you can make it a static property of the class:

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

    Or replace ?? by an if-statement:

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

    Addendum: Related resources:

    • Autoclosure of self in initializers in the Swift forum.
    • SR-944 Cannot use 'self' in RHS of && before all properties are initialized bug report.

    Quote from the bug report:

    Jordan Rose: This is true since && is implemented using @autoclosure, but it's certainly suboptimal.

    0 讨论(0)
提交回复
热议问题