Make self weak in methods in Swift

Robs answer worked for me. I did refactor it to be a little more OO though so I thought I would share it here in case it helps someone else:

public protocol WeakCallback{ 
    func invoke()
}

public class WeakCallbackInstance<T: AnyObject> : WeakCallback{
    private let callback: ()->Void
    private weak var target: T?

    public init(target: T, action: (T)->()->Void){

        self.target = target
        callback = { [weak target] in
            action(target!)()
        }
    }

    public func invoke(){
        callback()
    }
}

class ExampleUsage{

    func usage(){
        var callbacks = [WeakCallback]()

        let one = WeakCallbackInstance(target: DummyCallbackOne(), action:DummyCallbackOne.callbackOne)
        let two = WeakCallbackInstance(target: DummyCallbackTwo(), action:DummyCallbackTwo.callbackTwo)

        callbacks.append(one)
        callbacks.append(two)
        callbacks.first?.invoke()
    }
}

class DummyCallbackOne{
    func callbackOne(){
    }
}

class DummyCallbackTwo{
    func callbackTwo(){
    }
}

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