Make self weak in methods in Swift

wxs

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.

Example leaky code below:

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()})

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.

Rob Napier

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)

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)()

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).

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.)

EDIT: Here's the answer to that: https://devforums.apple.com/message/1036509#1036509

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

Swift - weak self in didSet

how to make a weak pointer to self in swift outside of a block

weak self in gcd in swift closure

Swift closures [weak self] and async tasks

Swift guarding weak self for nested callbacks

Is it the right way using `[weak self]` in swift closure?

When to use [self] vs [weak self] in swift blocks?

Swift: Assign a class method to a handler and handling weak self

Swift weak reference going nil even when self keeps existing

Swift: Maintaining atomicity in a block-based execution using weak self

For swift references within view model, should self reference be weak or unknown?

Should I use [weak self] when calling an API in Swift

Difference between weak self vs weak self()

In Swift, if I have a closure capturing [weak self], is it good practice to unwrap the optional self at the beginning of the closure?

Weak self vs self when using closure defined in swift in objective c

with or without [weak self]

Weak Self in Blocks

__weak self not working as expected

'[weak self]' in RXSwift closures

Swift: should completion closure have error indication when weak self is nil?

Is it good to make methods return 'self' for chaining method calls?

Where does the weak self go?

Weak self in closures and consequences example

Avoiding [weak self] for simple operations?

async/await, Task and [weak self]

Weak Self in GCD, accessing TableView property of self

Swift calling static methods: type(of: self) vs explicit class name

Swift closures in autorelase pool accessing methods without self

Swift: `weak` reference in tuple