我有一个Swift类,需要存储自己的方法表。不幸的是,这导致了一个引用周期,因为它的表self通过其存储的方法保留了对它的引用。
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在上述丑陋的封闭包装上构建作为语法糖的便捷功能。
myCallbacks
myCallbacks : [WeakCallback]()
weaken
您当然可以为此构建一个函数。我不知道它是否可以使它变得更好,但是它不容易出错。
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)。
T
(input) -> (output)
(T) -> (input) -> (output)
万一您好奇(我曾经),在这种情况下,覆盖可以正常工作。因此,如果您子类化CycleInducingClass并重写myInternalFunction,则会调用正确的版本。(这实际上让我感到有些惊讶,但我还不知道它为什么起作用,但确实如此。)
CycleInducingClass
myInternalFunction
编辑:这是答案:https : //devforums.apple.com/message/1036509#1036509