Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Weak reference to closure in Swift

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.

like image 546
lintmouse Avatar asked Jun 04 '15 02:06

lintmouse


People also ask

What is a weak reference in Swift?

Weak References. A weak reference is a reference that doesn't keep a strong hold on the instance it refers to, and so doesn't stop ARC from disposing of the referenced instance. This behavior prevents the reference from becoming part of a strong reference cycle.

How can you avoid strong reference cycles in a closure?

A strong reference cycle happens when 2 instances keep a strong reference to each other. You can accidentally create such a cyclic reference, for example when working with 2-way “links” between objects, or with closures. You can break the cycle by marking a reference as weak, or by setting one of the references to nil.

How do you make a weak reference in Swift?

Before you learn about strong and weak reference, make sure to understand how classes and objects work in Swift. Note: The declaration of a property is strong by default. To declare a weak reference we use the weak keyword.

What is strong and weak reference in Swift?

In Swift, a strong reference is the default, for variables, properties, constants, passing into functions (depending on what you do with it), and for closures. With ARC, an instance is only deallocated when its retain count is zero. A strong reference increases the retain count by 1, a weak reference does not.


1 Answers

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.

like image 60
matt Avatar answered Nov 13 '22 17:11

matt