持有函数swift的惰性初始化变量

时间:2015-08-04 00:04:37

标签: swift oop uiviewcontroller lazy-initialization

关于如何对保存函数的类变量进行延迟初始化,我有一个问题。在我正在进行的项目中 - 在视图控制器中 - 我需要根据在创建视图控制器后才能知道的信息运行一个函数。因此,我想使用延迟初始化来解决这个问题。我想我可以通过其他方式解决问题,但现在我很好奇我对懒惰初始化的理解,我很难弄清楚如何获得一个懒惰的初始化变量来保存函数。也就是说,如果它可以完成。

以下是我想要做的一些示例代码。我希望能够在talk()的实例上调用TestClass,然后此实例(在这种情况下为tc)调用f()foobar取决于具体情况。

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更改为:

    lazy var f: TestClass->()->() = {
        return foo
    }()

这再次无效,现在我收到错误Missing argument for parameter #1 in call

任何人都可以了解如何使用包含函数的变量进行延迟初始化?我知道我可以通过不使用延迟初始化来解决这个问题,但我希望有人可以帮助我理解我在这种情况下做错了什么。感谢。

2 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:2)

您需要明确说明self

lazy var f: ()->() = {
    return self.foo
}()