Swift – Weak reference to closure in Swift

closuresswiftweak-references

I have the following code to create an observable property for data binding. It's in the works so I'm not sure what the final implementation is going to be and I'm still pretty new to Swift.

class Observable<T> {
    typealias Observer = T -> Void

    var value: T {
        didSet {
            for observer in self.observers {
                observer?(self.value)
            }
        }
    }

    var observers: [Observer?] = []

    init(_ val: T) {
        self.value = val
    }
}

I would like to keep weak references to the Observer closures. I don't want to rely on the client to ensure that the closure is weak/unowned before passing it in, via the capture list. Especially because there can be many observable properties on a given class.

Is it possible to make the closure references weak in my Observable class?

UPDATE:

I found a couple of resources that I think will help me accomplish what I want:

Make self weak in methods in Swift

specifically,

func methodPointer<T: AnyObject>(obj: T, method: (T) -> () -> Void) -> (() -> Void) {
  return { [unowned obj] in method(obj)() }
}

The following link refers to the above stackoverflow answer and goes into some more detail:

http://blog.xebia.com/2014/10/09/function-references-in-swift-and-retain-cycles/

and this is a two-way binding example:

http://five.agency/solving-the-binding-problem-with-swift/

specifically,

class BondBox<T> {
  weak var bond: Bond<T>?
  init(_ b: Bond<T>) { bond = b }
}

where the listener is wrapped in a class called Bond, which is weakly referenced in the BondBox.

Best Answer

Is it possible to make the closure references weak in my Observable class

No. Only class instances can be referred to via weak references in Swift, and a function is not a class instance. (And not only must they be class instances, they must be an Optional wrapping a class instance.)

There are some pretty obvious ways around this, or course - the simplest being a wrapper class. But I do not actually recommend that in this situation, because you have not convinced me that weak references to functions are needed here in the first place. Remember, a weak reference to an object to which there is no strong reference will instantly lose the reference and will be pointing at nil. I can't believe that is what you want. I think you're barking up a wrong tree here.