Here is my custom view:
class CustomVIew: UIView {
deinit {
print("custom view deinit")
}
var onTapViewHandler: (()->Void)?
}
and the View Controller:
class ViewControllerB: UIViewController {
var customView: CustomVIew!
deinit {
print("B deinit")
}
override func viewDidLoad() {
super.viewDidLoad()
let customView = CustomVIew()
customView.onTapViewHandler = { [unowned self] in
self.didTapBlue()
}
customView.frame = CGRect(x: 50, y: 250, width: 200, height: 100)
customView.backgroundColor = UIColor.blueColor()
view.addSubview(customView)
self.customView = customView
}
func didTapBlue() {
}
}
When the controller is popped from the navigation stack, everything is fine:
B deinit
custom view deinit
But when I replace this code:
customView.onTapViewHandler = { [unowned self] in
self.didTapBlue()
}
with this:
customView.onTapViewHandler = didTapBlue
then, nothing is printed on the console. The CustomView and ViewController are not released, why?
Why does customView.onTapViewHandler = didTapBlue
capture a reference to self
?
— in order to deallocate an object from memory, its ARC value must be zero. However, when some two object refers each other via strong references, they prevent the compiler from deallocating either object because their ARC value would always be 1. That is called a retain cycle.
An essential concept in ARC is the retain count, which is a number that keeps track of how many objects are “holding onto” to another object. ARC only applies to reference types such as classes, and not to value types like structs. Value types are copied, so they don't work with references.
Structs and Classes A choice between a struct and a class can cause a retain cycle. Both structs and classes can have constants, variables, functions and protocols.
Swift function is a type of closure. So like closure(Block in objective c) does functions can capture references.
when customView.onTapViewHandler = didTapBlue
gets executes a reference to self
ie ViewControllerB
reference in this case will be captured by the function call.
Same time ViewControllerB
's view holds strong reference to CustomVIew
so it makes retain cycle.
About using unowned
, Apple document says:
Weak and unowned references enable one instance in a reference cycle to refer to the other instance without keeping a strong hold on it. The instances can then refer to each other without creating a strong reference cycle.
That means no circular reference and retain cycle.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With