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更改.两个示例都编译没有错误.
有趣的。
如果您避免在闭包内引用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 进行测试
希望这可以帮助。
| 归档时间: |
|
| 查看次数: |
5381 次 |
| 最近记录: |