Swift delegation - when to use weak pointer on delegate - swift

Can someone explain when and when not to use a 'weak' assignment to a delegate pointer in Swift, and why?
My understanding is that if you use a protocol that is not defined as a class you cannot, nor want to, assign your delegate pointer to weak.
protocol MyStructProtocol{
//whatever
}
struct MyStruct {
var delegate: MyStructProtocol?
}
However, when your protocol is defined as a class type protocol then you DO want to set your delegate to a weak pointer?
protocol MyClassProtocol: class{
//whatever
}
class MyClass {
weak var delegate: MyClassProtocol?
}
Am I correct? In Apple's swift guide there class protocol examples aren't using weak assignments, but in my testing I'm seeing strong reference cycles if my delegates aren't weakly referenced.

You generally make class protocols weak to avoid the risk of a “strong reference cycle” (formerly known as a “retain cycle”). (Note, we now do that by adding the AnyObject protocol to a protocol’s inheritance list; see Class-Only Protocols; we do not use the class keyword anymore.) Failure to make the delegate weak does not mean that you inherently have a strong reference cycle, but merely that you could have one.
With struct types, though, the strong reference cycle risk is greatly diminished because struct types are not “reference” types, so it is harder to create strong reference cycle. But if the delegate object is a class object, then you might want to make the protocol a class protocol and make it weak.
In my opinion, making class delegates weak is only partially to alleviate the risk of a strong reference cycle. It also is a question of ownership. Most delegate protocols are situations where the object in question has no business claiming ownership over the delegate, but merely where the object in question is providing the ability to inform the delegate of something (or request something of it). E.g., if you want a view controller to have some text field delegate methods, the text field has no right to make a claim of ownership over the view controller.

As Rob said:
It's really a question of "ownership"
That's very true. 'Strong reference cycle' is all about getting that ownership right.
In the following example, we're not using weak var. Yet both objects will deallocate. Why?
protocol UserViewDelegate: class {
func userDidTap()
}
class Container {
let userView = UserView()
let delegate = Delegate()
init() {
userView.delegate = delegate
}
deinit {
print("container deallocated")
}
}
class UserView {
var delegate: UserViewDelegate?
func mockDelegatecall() {
delegate?.userDidTap()
}
deinit {
print("UserView deallocated")
}
}
class Delegate: UserViewDelegate {
func userDidTap() {
print("userDidTap Delegate callback in separate delegate object")
}
}
Usage:
var container: Container? = Container()
container?.userView.mockDelegatecall()
container = nil // will deallocate both objects
Memory ownership graph (doesn't have cycle)
+---------+container +--------+
| |
| |
| |
| |
| |
| |
v v
userView +------------------> delegate
In order to create a strong reference cycle, the cycle needs be complete. delegate needs to point back to container but it doesn't. So this isn't an issue. But purely for ownership reasons and as Rob has said here:
In an object hierarchy, a child object should not maintain strong references to the parent object. That is a red flag, indicating a strong reference cycle
So regardless of leaking, still use weak for your delegate objects.
In the following example, we're not using weak var. As a result neither of the classes will deallocate.
protocol UserViewDelegate: class {
func userDidTap()
}
class Container: UserViewDelegate {
let userView = UserView()
init() {
userView.delegate = self
}
func userDidTap() {
print("userDidTap Delegate callback by Container itself")
}
deinit {
print("container deallocated")
}
}
class UserView {
var delegate: UserViewDelegate?
func mockDelegatecall() {
delegate?.userDidTap()
}
deinit {
print("UserView deallocated")
}
}
Usage:
var container: Container? = Container()
container?.userView.mockDelegatecall()
container = nil // will NOT deallocate either objects
Memory ownership graph (has cycle)
+--------------------------------------------------+
| |
| |
+ v
container userview
^ |
| |
| |
+------+userView.delegate = self //container+------+
using weak var will avoid the strong reference cycle

Delegates should always generally be weak.
Lets say b is the delegate of a. Now a's delegate property is b.
In a case where you want b to release when c is gone
If c holds a strong reference to b and c deallocates, you want b to deallocate with c. However, using a strong delegate property in a, b will never get deallocated since a is holding on to b strongly. Using a weak reference, as soon as b loses the strong reference from c, b will dealloc when c deallocs.
Usually this is the intended behaviour, which is why you would want to use a weak property.

Related

Swift Reference Cycle When Capturing A Computed String Property Declared From Inside An Instance Method

I'm implementing an in-game store using Swift and SpriteKit. There is a class called Store which has a method setupItems() inside of which we declare and instantiate instances of a class StoreItem and also add each store item instance as a child of Store. Each StoreItem has an optional closure property called updateInventory which is set inside of setupItems() as well. This is an optional closure because some items don't have a limited inventory.
Store also has an unowned instance property storeDelegate which is responsible for determining how funds are deducted and how storeItems are applied once purchased. storeDelegate is unowned as it has an equal or greater lifetime than Store.
Now, here is where things get interesting - the closure updateInventory references a computed string variable called itemText which makes a calculation based on a property of storeDelegate. If itemText is declared and instantiated as a variable inside of setupItems() we have a reference cycle and store is not deallocated. If instead, itemText is declared and instantiated as an instance property of Store (right under the property unowned storeDelegate that it references) then there is no reference cycle and everything deallocates when it should.
This seems to imply that referencing storeDelegate from a computed variable inside an instance method of a class doesn't respect the unowned qualifier. Code examples follow:
Current Scenario
protocol StoreDelegate: AnyObject {
func subtractFunds(byValue value: Int)
func addInventoryItem(item: InventoryItem) throws
var player: Player! { get }
}
class Store: SKSpriteNode, StoreItemDelegate {
unowned var storeDelegate: StoreDelegate
init(storeDelegate: StoreDelegate) {
self.storeDelegate = storeDelegate
setupItems()
...
}
func setupItems() {
var itemText: String {
return "item info goes here \(storeDelegate.player.health)"
}
let storeItem = StoreItem(name: "coolItem")
storeItem.updateInventory = {
[unowned storeItem, unowned self] in
// some logic to check if the update is valid
guard self.storeDelegate.player.canUpdate() else {
return
}
storeItem.label.text = itemText
}
}
The above leads to a reference cycle, interestingly if we move
var itemText: String {
return "item info goes here \(storeDelegate.player.health)"
}
outside of updateItems and make it an instance variable of Store right below unowned var storeDelegate: StoreDelegate, then there is no reference cycle.
I have no idea why this would be the case and don't see mention of it in the docs. Any suggestions would be appreciated and let me know if you'd like any additional details.
storeItem.updateInventory now keeps strong reference to itemText.
I think the issue is that itemText holds a strong reference to self implicitly in order to access storeDelegate, instead of keeping a reference to storeDelegate. Anothe option is that even though self is keeping the delegate as unowned, once you pass ot to itemText for keeping, it is managed (ie, strong reference again).
Either way, you can guarantee not keeping strong reference changing itemText to a function and pass the delegate directly:
func setupItems() {
func itemText(with delegate: StoreDelegate) -> String
return "item info goes here \(storeDelegate.player.health)"
}
let storeItem...
storeItem.updateInventory = {
// ...
storeItem.label.text = itemText(with self.storeDelegate)
}
}

memory leak with swift due to reference cycle

Can someone please help me to avoid memory leak below
class Base {
var refer: Referenced?
init() {
self.refer = Referenced()
}
deinit {
print("deinit called")
}
}
class Referenced {
var native: Native
init(){
native = Native.init(baseRef: Base())
}
}
struct Native {
var baseRef: Base
}
func testMe () {
var base:Base? = Base()
base?.refer = nil
base = nil
}
testMe()
Looks like there is a cyclic reference in here. Base -> Referenced and Referenced -> Native -> Base
But I am unsure how to break this cycle .
There are two issues here:
As others have pointed out, in general, when you have two or more reference types referring to each other, you need to make one of those references weak to break the strong reference cycle. See Resolving Strong Reference Cycles Between Class Instances.
The more serious problem here is that you have infinite loop. The init of Base is instantiating a new Referenced instance, but the init of Referenced is creating another Base instance (which it’s passing to the Native instance). That new Base instance will then create another Referenced instance, repeating the process, and it will continue doing this until it runs out of memory/stack.
Add print statements inside your various init methods, and you’ll see this infinite loop in action.
You should revisit this model, identify an “ownership” graph. Parent objects can keep strong references to child objects (and possibly instantiate child objects, if appropriate), but child objects should only keep weak references back to their parent objects (and most likely not instantiate new parent objects).
For example, you might do:
class Parent {
var child: Child?
init() {
self.child = Child(parent: self)
}
deinit {
print("deinit called")
}
}
class Child {
weak var parent: Parent?
init(parent: Parent) {
self.parent = parent
}
}
And
func testMe() {
var parent: Parent? = Parent()
parent = nil // in this case, this is unnecessary because `parent` is a local variable, but this is here for illustrative purposes; but note that we don’t have to `nil` the `child`
}
Here, you instantiate a Parent object, which happens to instantiate a child. But note that:
The Parent supplies itself as a parameter to the Child;
The Child only maintains a weak reference back to the Parent; and
The Child obviously does not instantiate a new Parent, but rather just uses the reference that was supplied to it.
You can do a rendition of this with your Native struct, too, but the idea will be the same: Break the strong reference cycle with a weak reference and avoid the infinite loop.
Frankly, in these cases, abstract type names make examples unnecessarily confusing. If you clarify what these various types actual represent with a practical, real-world example, the ownership model will undoubtedly become more self-evident.
Change one of the reference as weak like this :
class Base {
weak var refer: Referenced?
init() {
self.refer = Referenced()
}
deinit {
print("deinit called")
}
}
Hope this helps.
You need to mark either Base.refer or Native.baseRef as weak to break the cycle, i.e. change var to weak var.
First of all, at the code snippet you passed, you have a problem with infinite circular dependency like this:
Base -> Referenced -> Native -> Base...
An instance of Native struct is not referencing the Base instance at the beginning of this chain, it is always creating a new one and this behavior is infinite. Just copy your code to the playground and try to run it. You will receive an "Execution was interrupted" error.
So, your code won't even run. As I suppose, what you are trying to achieve is for a Native struct to hold the reference to the first Base instance. Here is the right solution where we pass the reference from Base to Referenced and to Native that will hold the reference:
class Base {
var refer: Referenced?
init() {
self.refer = Referenced(base: self)
}
deinit {
print("deinit called")
}
}
class Referenced {
var native: Native
init(base: Base){
native = Native.init(baseRef: base)
}
}
struct Native {
var baseRef: Base
}
And now, as Native is referencing to the Base parent, you will struggle with the memory leak you mention in the original question. And this time, to prevent the memory leak you have to make your baseRef var weak like this:
weak var baseRef: Base?

Setting a delegate generates a compile error

I want to use a strategy pattern to register a set of objects that implement a protocol. When I set this up, I get a compile error when trying to set the delegate that is part of the protocol.
For discussion purposes, I have slightly reworked the DiceGame from the Swift eBook's Delegation chapter. The changes of significance are:
protocol DiceGame - declares a delegate
class SnakesAndLadders implements DiceGame (and therefore the protocol and delegate)
class Games holds 3 instances of SnakesAndLadders as
1) a concrete class of SnakesAndLadders
2) a 'let' constant of protocol DiceGame
3) a 'var' variable of protocol DiceGame
We can set the delegate fine if we use the concrete class (snakesAndLadders). However, there is a compile error if we use 'let' to hold it as a protocol (diceGameAsLet) but it compiles if we hold the variable as a 'var' (diceGameAsVar).
It is easy to work around, however, the delegate itself never changes so should be held as a 'let' constant, as it is only the internal property that changes. I must not understand something (possibly subtle but significant) about protocols and how they work and should be used.
class Dice
{
func roll() -> Int
{
return 7 // always win :)
}
}
protocol DiceGame
{
// all DiceGames must work with a DiceGameDelegate
var delegate:DiceGameDelegate? {get set}
var dice: Dice {get}
func play()
}
protocol DiceGameDelegate
{
func gameDidStart( game:DiceGame )
func gameDidEnd( game:DiceGame )
}
class SnakesAndLadders:DiceGame
{
var delegate:DiceGameDelegate?
let dice = Dice()
func play()
{
delegate?.gameDidStart(self)
playGame()
delegate?.gameDidEnd(self)
}
private func playGame()
{
print("Playing the game here...")
}
}
class Games : DiceGameDelegate
{
let snakesAndLadders = SnakesAndLadders()
// hold the protocol, not the class
let diceGameAsLet:DiceGame = SnakesAndLadders()
var diceGameAsVar:DiceGame = SnakesAndLadders()
func setupDelegateAsClass()
{
// can assign the delegate if using the class
snakesAndLadders.delegate = self
}
func setupDelegateAsVar()
{
// if we use 'var' we can assign the delegate
diceGameAsVar.delegate = self
}
func setupDelegateAsLet()
{
// DOES NOT COMPILE - Why?
//
// We are not changing the dice game so want to use 'let', but it won't compile
// we are changing the delegate, which is declared as 'var' inside the protocol
diceGameAsLet.delegate = self
}
// MARK: - DiceGameDelegate
func gameDidStart( game:DiceGame )
{
print("Game Started")
}
func gameDidEnd( game:DiceGame )
{
print("Game Ended")
}
}
DiceGame is a heterogeneous protocol that you're using as a type; Swift will treat this type as a value type, and hence (just as for a structures), changing its mutable properties will mutate also the instance of the protocol type itself.
If you, however, add the : class keyword to the DiceGame protocol, Swift will treat it as a reference type, allowing you to mutate members of instances of it, without mutating the instance itself. Note that this will constraint the protocol as conformable to only by class types.
protocol DiceGame: class { ... }
With the addition of the above, the mutation of immutable diceGameAsLet:s properties will be allowed.
In this context, it's worth mentioning that the : class keyword is usually used to constrain protocols used as delegates (e.g., DiceGameDelegate in your example) as conformable to only by class types. With this additional constraint, the delegates can be used as types to which the delegate owner (e.g. some class) only hold a weak reference, useful in contexts where a strong reference to the delegate could create a retain cycle.
See e.g. the 2nd part of this answer for details.
The issue is that when you store something as a Protocol, even if it is a class, swift considers them to be a value type, instead of the reference type you are expecting them to be. Therefore, no part of it is allowed to be changed. Take a look at this reference for more information.

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

Zeroing weak variable and deinit, which one happens first?

Which one happens first?
Zeroing (nilling) weak variable.
deinit
Without looking at the documentation, nor implementation...
Only one order makes sense: nilling has to come first.
If deinitialization would start before nilling weak references ARC would suffer the good old resurrection problem (retaining an object that is in the process of being deallocated). That is not the case.
Here's my mental model of object destruction (again, not from the documentation, this can differ from real world):
last strong reference to an object goes away
retain count goes to zero (logically)
object is internally flagged for destruction, disabling any more new references
all weak references are nilled
unowned reference count is checked and traps if non-zero
deinit chain is called, possibly calling through to objc base classes dealloc
strong references to properties and ivars go away
objc side effects of dtor happen (associated objects, c++ destruction, ...)
memory is reclaimed
Step 1 through 4 happen atomically with regards to other threads potentially taking new strong references to the object.
Zeroing weak variable happens first. deinit happens later. At least in current implementation (Xcode 6.1, Swift 1.1) This is a result of observation of specific implementation, and I don't know how it is actually defined by the authors... If you have explicit source, please comment or answer.
There's also a related discussion in ADC forum.
Test code Avoid Playground when testing this to get correct lifecycle behaviour.
class AAA {
func test() {
}
}
var a1 = nil as AAA?
weak var a2 = nil as AAA?
class BBB: AAA {
var data = "Here be dragons."
override func test() {
println("test() called and a2 is now \(a2).")
}
deinit {
println("deinit called and a2 is now \(a2).")
}
}
a1 = BBB()
a2 = a1
a2!.test()
a1 = nil
Result:
test() called and a2 is now Optional(weak_deinit_order_comparison.BBB).
deinit called and a2 is now nil.
Then, the weak variable becomes nil before the deinit to be called.
Update
This pre-nilling is applied equally to unowned objects. Unowned object will become inaccessible at the point of deist just like weak, and trial to access unowned object at the deinit will crash the app.
Update 2
If you assign self to a weak var variable in deinit, it will become nil immediately. (Xcode Version 6.3.2 (6D2105))
class Foo {
init() {
}
deinit {
var a = self
weak var b = self
unowned var c = self
let d = Unmanaged.passUnretained(self)
println(a) // prints `Foo`.
println(b) // prints `nil`.
// println(c) // crashes.
println(d.takeUnretainedValue()) // prints `Foo`.
}
}
var f = Foo() as Foo?
f = nil