在实例初始化程序中将实例方法作为回调传递

时间:2017-07-09 23:28:54

标签: swift

请考虑以下代码:

class Bar {
    let callback: () -> ()

    init(callback: @escaping () -> ()) {
        self.callback = callback
    }

    func event() {
        self.callback()
    }
}

class Foo {
    let bar: Bar

    init() {
        self.bar = Bar(callback: self.handler)
    }

    func handler() {
        print("Handled")
    }
}

我们的基本想法是,我们希望每个Foo都有一个Bar,当event() {{1} Foo被调用时},将调用bar的处理程序方法。但是,上面的设置会在Foo初始化时发出警告,因为我们在初始化所有实例属性之前使用Foo

我理解为什么这是一个错误:编译器不能保证传递给self的初始化程序的方法不会在{{1}之前以某种方式被调用}}初始化程序完成(例如Bar可以在其初始化程序中调用Foo参数,或者其他帖子可能在{{1}之后调用Bar初始化程序返回,但就在将结果分配给callback event())之前。

我的问题是,有没有办法实现我错过的这种模式?一种解决方法是将Bar设为IUO Foo,并在致电bar bar之前将其分配给var - 只要< em>我们知道在不适当的时间(或者只要我们不在nil中使用Bar)就不会调用回叫,那么就不应该这样做。是一个问题。然而,这对我来说感觉很糟糕,如果它们存在,我会喜欢听取替代品。

1 个答案:

答案 0 :(得分:4)

这是另一种选择:

class Foo {
    let bar: Bar

    init() {
        self.bar = Bar(callback: self.handler)
    }

    let handler: () -> Void = {
        print("handled")
    }
}

也许它不会感觉像hacky,但如果handler完全处理self,这将无效。你也不能用代表来做。

是的,AFAIK,这样做的唯一方法是让bar隐式展开var

class Foo {
    var bar: Bar!

    init() {
        bar = Bar(callback: handler)
    }

    func handler() {
        print("Handled")
    }
}