4
votes

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.

2
I think it's possible with swift 5.2's callAsFunctionHai Feng Kao

2 Answers

5
votes

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.

-2
votes

Weak/strong are for memory management of objects, so only apply for variables of reference types (i.e. types which point to objects). Function types in Swift are not reference types, and therefore it does not make sense to talk about weak/strong for their variables.

Plus, you do not actually have variables of function type in your code (except in the middle of the iteration). You simply have a variable of array type. Even in Objective-C, you can only mark variables as weak or strong, not values that are stored inside other things.

And if you were to write the thing you are writing in Objective-C, you would want the "Observable" to have strong references to the closures. Otherwise, who else would have a strong reference to the closure?