在Swift中使自身变得脆弱 [英] Make self weak in methods in Swift
问题描述
我有一个Swift类,需要存储自己的方法表.不幸的是,这导致了引用循环,因为它的表通过其存储的方法保留了对self
的引用.
I have a Swift class that needs to store a table of its own methods. Unfortunately this is causing a reference cycle, because its table retains references to self
via the methods it stores.
以下示例泄漏代码:
typealias Callback = ()->()
class CycleInducingClass : NSObject {
var myCallbacks = [Callback]()
override init() {
super.init()
myCallbacks.append(myInternalFunction)
}
func myInternalFunction() {
NSLog("lolol: %d", self.myCallbacks.count)
}
}
到目前为止,我发现的唯一解决方案是改为执行此操作:
The only solution I've found so far is to instead do this:
myCallbacks.append({[unowned self] in self.myInternalFunction()})
这很丑陋,而且容易出错.还有更好的主意吗?是否有一些使函数引用本身变弱的技巧?即使myCallbacks
类型为myCallbacks : [WeakCallback]()
的数组?据我所知,我什至无法在上面的丑陋的封套包装上建立方便功能weaken
作为语法糖.
That's pretty ugly, and prone to error. Any better ideas? Is there some trick for making the function references themselves be weak? i.e. to make the myCallbacks
array of type myCallbacks : [WeakCallback]()
or something? As far as I can tell I can't even build a convenience function weaken
as syntactic sugar over the ugly closure wrapper above.
推荐答案
您当然可以为此构建一个函数.我不知道它是否可以使它变得更好,但是它不容易出错.
You can certainly build a function for this. I don't know if it makes it dramatically better, but it is less error-prone.
func methodPointer<T: AnyObject>(obj: T, method: (T) -> () -> Void) -> (() -> Void) {
return { [unowned obj] in method(obj)() }
}
...
myCallbacks.append(methodPointer(self, CycleInducingClass.myInternalFunction))
或者,您可以将回调作为方法指针进行管理:
Alternately, you could manage your callbacks as method pointers:
typealias Callback = (CycleInducingClass) -> () -> Void
...
myCallbacks.append(CycleInducingClass.myInternalFunction)
在这种情况下,您需要在调用它们时传递self
(如果您实际上不做很多事情,这可能会很好):
In that case, you'd need to pass self
when you called them (which may be fine if you don't actually do this a lot):
self.myCallbacks[0](self)()
所有这些基于以下事实:签名为(input) -> (output)
的类型为T
的方法等效于签名为(T) -> (input) -> (output)
的函数.
All of this is based on the fact that a method on type T
with signature (input) -> (output)
is equivalent to a function with the signature (T) -> (input) -> (output)
.
如果您好奇(我曾经),那么在这种情况下,重写可以正常工作.因此,如果子类CycleInducingClass
并覆盖myInternalFunction
,则将调用正确的版本. (这实际上让我感到有些惊讶,但我还不知道它为什么起作用,但确实如此.)
In case you're curious (I was), overriding works correctly in this case. So if you subclass CycleInducingClass
and override myInternalFunction
, the correct version will be called. (That actually surprises me a little, and I don't yet know exactly why it works, but it does.)
这是答案: https://devforums.apple.com/message/1036509#1036509
这篇关于在Swift中使自身变得脆弱的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!