Swift变量在使用前未初始化(但未使用)

Pup*_*ppy 10 closures initializer swift

目前我有一些像这样的快速代码:

class C {
   let type: Type;
   var num = 0;
   init() {
       self.type = Type({ (num: Int) -> Void in
           self.num = num;
       });
   }
}
Run Code Online (Sandbox Code Playgroud)

Swift编译器拒绝允许它,说我self.type在它初始化之前引用了它,尽管这显然是完全不真实的.此外,我不能使用在其他问题/答案中找到的解决方法,因为type它不是可选的,并且它是不可变的,所以它无法nil首先无意义地初始化.

如何让Swift编译器接受这个完全有效的代码?

这与早期从初始化程序返回无关.回调是异步执行的 - 它被存储然后再使用.

我还有一些let在此之后初始化的s.我必须将它们全部变成可变的选项,即使它们不是可选的并且不能被变异.

Ger*_*tan 10

这有效:

class C {
    var type: Type?;
    var num = 0;
    init() {
        self.type = Type({ (num: Int) -> Void in
            self.num = num;
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

我猜你知道的.但是你想知道你的版本无法正常工作的原因.

现在是棘手的部分:为线

self.num = num;
Run Code Online (Sandbox Code Playgroud)

为了工作,编译器必须将self传递给闭包内部.闭包可能并且可能在Type的构造函数内执行.

这就像你写的那样

self.type = Type({ (self: C, num: Int) -> Void in
    self.num = num    
});
Run Code Online (Sandbox Code Playgroud)

这在语法上是错误的,但解释了编译器编译代码时必须做什么.

要将此必需的self实例传递给Type的构造函数,必须初始化self.但是self没有初始化,因为你仍然在构造函数中.

当您尝试将self传递给Type的构造函数时,编译器会告诉您哪个self部分未初始化.

PS

显然Type在你的代码中知道num.如果你想在C中使用let而不是var,你可以做...

class Type {
    let num: Int
    init () {
        num = 3
    }
}
class C {
    let type: Type;
    var num = 0;
    init() {
        self.type = Type();
        num = type.num
    }
}
Run Code Online (Sandbox Code Playgroud)

甚至

class C {
    let type: Type;
    var num: Int {
        return type.num
    }
    init() {
        self.type = Type();
    }
}
Run Code Online (Sandbox Code Playgroud)

取决于你是否想要num更改.两个示例都编译没有错误.

  • 是的,如果你使用var和optionals.但是你使用let而不是可选的,必须先将其初始化,然后才能在其他地方使用self. (3认同)

Luc*_*tti 2

有趣的。

如果您避免在闭包内引用self,那么错误似乎就会消失。

如果回调是同步的,您可以按如下方式更改代码:

class C {
    let type: Type
    var num = 0
    init() {
        var numTemp = 0 // create a temporary local var
        let initialType = Type({ (num: Int) -> () in
            numTemp = num // avoid self in the closure
        });
        self.type = initialType
        self.num = numTemp
    }
}
Run Code Online (Sandbox Code Playgroud)

重要提示:如果闭包是异步的,这将不起作用。

使用 Xcode (Playground) 6.4 + Swift 1.2 进行测试

希望这可以帮助。