我有一个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]()还是什么?据我所知,我甚至不能建立一个方便的功能,削弱了上面的丑陋的封面包装上的句法糖。
你可以为此建立一个功能。我不知道它是否会使其显着改善,但是容易出错。
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.myCallbacks[0](self)()
所有这一切都是基于一个事实,即一个带有签名(输入)的类型T的方法 – > (输出)等价于具有签名(T)的函数 – > (输入) – > (输出)。
如果你好奇(我是),在这种情况下,重写工作是正确的。因此,如果您将CycleInducingClass子类化并覆盖myInternalFunction,则将调用正确的版本。 (这真的让我感到惊讶,我还不知道为什么它的作品,但它是。)