持有函数的惰性初始化变量 swift
Lazy initialized variable holding a function swift
我有一个关于如何对包含函数的 class 变量进行延迟初始化的问题。在我正在处理的项目中 - 在视图控制器中 - 我需要 运行 一个基于信息的函数,我只会在创建视图控制器后才知道。因此,我想使用惰性初始化来解决这个问题。我想我可以通过其他方式解决问题,但现在我很好奇我对延迟初始化不了解的地方,以至于我很难弄清楚如何获取延迟初始化的变量来保存函数。也就是说,如果完全可以做到的话。
这是我正在尝试做的一些示例代码。我希望能够在 TestClass
的实例上调用 talk()
,然后这个实例(在本例中为 tc
)调用 f()
,它是 foo
或bar
视情况而定。
class TestClass {
func foo() {
println("foo")
}
func bar() {
println("bar")
}
lazy var f: ()->() = {
return foo
}()
func talk() {
f()
}
}
var tc = TestClass()
tc.f()
现在,这没有编译,我得到错误:
Playground execution failed: swiftTesting.playground:28:30: error: 'TestClass -> () -> ()' is not convertible to '() -> ()'
lazy var f: ()->() = {
然后我尝试将我的 f
惰性变量更改为:
lazy var f: TestClass->()->() = {
return foo
}()
这又没有用,现在我得到了错误,Missing argument for parameter #1 in call
。
任何人都可以阐明如何使用包含函数的变量进行惰性初始化吗?我知道我可以通过不使用延迟初始化来解决这个问题,但我希望有人能帮助我理解在这种情况下我做错了什么。谢谢。
您需要明确说明 self
:
lazy var f: ()->() = {
return self.foo
}()
foo
是一个实例方法,但是闭包通过不自动绑定到它来避免对 self
的隐式捕获。你需要明确地说 self.foo
.
lazy var f: ()->() = {
return self.foo
}()
tc.f()
// tc is leaked, see below
当您改为使用 TestClass->()->()
时,该方法未绑定任何内容,因此您需要为其提供一个实例。
lazy var f: TestClass->()->() = {
return foo
}()
tc.f(tc)() // Call f with tc to give it an instance, then call the result
第一个选择看起来不错,但实际上会阻止tc
被释放。将 foo
绑定到 self
并将其存储在 self
中会导致引用循环。为了避免这种情况,你需要使用一个弱捕获自我的闭包。
lazy var f: ()->() = {
[weak self] in
self!.foo() // ! because self is optional due to being weak
} // no () here
tc.f()
// tc can be deallocated
我有一个关于如何对包含函数的 class 变量进行延迟初始化的问题。在我正在处理的项目中 - 在视图控制器中 - 我需要 运行 一个基于信息的函数,我只会在创建视图控制器后才知道。因此,我想使用惰性初始化来解决这个问题。我想我可以通过其他方式解决问题,但现在我很好奇我对延迟初始化不了解的地方,以至于我很难弄清楚如何获取延迟初始化的变量来保存函数。也就是说,如果完全可以做到的话。
这是我正在尝试做的一些示例代码。我希望能够在 TestClass
的实例上调用 talk()
,然后这个实例(在本例中为 tc
)调用 f()
,它是 foo
或bar
视情况而定。
class TestClass {
func foo() {
println("foo")
}
func bar() {
println("bar")
}
lazy var f: ()->() = {
return foo
}()
func talk() {
f()
}
}
var tc = TestClass()
tc.f()
现在,这没有编译,我得到错误:
Playground execution failed: swiftTesting.playground:28:30: error: 'TestClass -> () -> ()' is not convertible to '() -> ()'
lazy var f: ()->() = {
然后我尝试将我的 f
惰性变量更改为:
lazy var f: TestClass->()->() = {
return foo
}()
这又没有用,现在我得到了错误,Missing argument for parameter #1 in call
。
任何人都可以阐明如何使用包含函数的变量进行惰性初始化吗?我知道我可以通过不使用延迟初始化来解决这个问题,但我希望有人能帮助我理解在这种情况下我做错了什么。谢谢。
您需要明确说明 self
:
lazy var f: ()->() = {
return self.foo
}()
foo
是一个实例方法,但是闭包通过不自动绑定到它来避免对 self
的隐式捕获。你需要明确地说 self.foo
.
lazy var f: ()->() = {
return self.foo
}()
tc.f()
// tc is leaked, see below
当您改为使用 TestClass->()->()
时,该方法未绑定任何内容,因此您需要为其提供一个实例。
lazy var f: TestClass->()->() = {
return foo
}()
tc.f(tc)() // Call f with tc to give it an instance, then call the result
第一个选择看起来不错,但实际上会阻止tc
被释放。将 foo
绑定到 self
并将其存储在 self
中会导致引用循环。为了避免这种情况,你需要使用一个弱捕获自我的闭包。
lazy var f: ()->() = {
[weak self] in
self!.foo() // ! because self is optional due to being weak
} // no () here
tc.f()
// tc can be deallocated