一尘不染

在Swift中使自身变得脆弱

swift

我有一个Swift类,需要存储自己的方法表。不幸的是,这导致了一个引用周期,因为它的表self通过其存储的方法保留了对它的引用。

以下示例泄漏代码:

typealias Callback = ()->()

class CycleInducingClass : NSObject {
    var myCallbacks = [Callback]()

    override init() {
        super.init()
        myCallbacks.append(myInternalFunction)
    }

    func myInternalFunction() {
        NSLog("lolol: %d", self.myCallbacks.count)
    }
}

到目前为止,我发现的唯一解决方案是改为执行此操作:

myCallbacks.append({[unowned self] in self.myInternalFunction()})

这很丑陋,而且容易出错。还有更好的主意吗?是否有一些使函数引用本身变弱的技巧?即使myCallbacks类型的数组myCallbacks : [WeakCallback]()或什么?据我所知,我什至无法weaken在上述丑陋的封闭包装上构建作为语法糖的便捷功能。


阅读 210

收藏
2020-07-07

共1个答案

一尘不染

您当然可以为此构建一个函数。我不知道它是否可以使它变得更好,但是它不容易出错。

func methodPointer<T: AnyObject>(obj: T, method: (T) -> () -> Void) -> (() -> Void) {
  return { [unowned obj] in method(obj)() }
}
...
myCallbacks.append(methodPointer(self, CycleInducingClass.myInternalFunction))

或者,您可以将回调作为方法指针进行管理:

typealias Callback = (CycleInducingClass) -> () -> Void
...
myCallbacks.append(CycleInducingClass.myInternalFunction)

在这种情况下,您需要self在呼叫他们时通过(如果您实际上不做很多事情,那可能会很好):

self.myCallbacks[0](self)()

所有这些都是基于这样一个事实,即T带有签名的类型方法(input) -> (output)等同于带有签名的函数(T) -> (input) -> (output)

万一您好奇(我曾经),在这种情况下,覆盖可以正常工作。因此,如果您子类化CycleInducingClass并重写myInternalFunction,则会调用正确的版本。(这实际上让我感到有些惊讶,但我还不知道它为什么起作用,但确实如此。)

编辑:这是答案:https :
//devforums.apple.com/message/1036509#1036509

2020-07-07