It is a great idea to always keep strong reference cycles in mind, but if we are too aggressive with the use of weak and unowned references, we can run into the opposite problem, where an object is deleted before we intended it to be.
With an object this will happen if all of the references to the object are weak or unowned. This won't be a fatal mistake if we use weak references, but if this happens with an unowned reference it will crash your program.
For example, let's look at the preceding example with an extra weak reference:
class SteeringWheel { weak var car: Car? } class Car { weak var steeringWheel: SteeringWheel! init(steeringWheel: SteeringWheel) { self.steeringWheel = steeringWheel steeringWheel.car = self } } let wheel = SteeringWheel() let car = Car(steeringWheel: wheel)
This code is the same as the preceding one except that both the car
property of SteeringWheel
and the steeringWheel
property of Car
are weak. This means that as soon as wheel
goes out of scope, it will be deleted, resetting the steeringWheel
property of the car to nil. There may be scenarios where you want this behavior, but often this will be unintentional and create confusing bugs.
The important thing is that you keep in mind all of the relationships an object has. There should always be at least one strong reference as long as you still want the object around and of course, there should never be a strong reference cycle.
This actually can't happen with closures because, as we discussed before, you cannot refer to a closure weakly. If you try, the compiler will give you an error:
class Ball2 { weak var onBounce: (() -> ())? // Error: 'weak' cannot be // applied to non-class type '() -> ()' }
Swift saves us from yet another type of bug.