Swift — weak, strong, optional, wrapped with IBOutlet . Confused?
When you connect any UI component(UIButton, UILabel, etc.) using IBOutlets to the Interface builder(Storyboard, XIB), generally you don't think much whether it is being used with weak/strong, optional, or implicitly wrapped. The real struggle comes when someone asks about the reason behind opting for it. Let's find out one acceptable answer for the same.
Apple’s recommendation on IBOutlets:
Let’s do some brainstorming with some valid pointers and try to conclude.
Weak vs Strong
#1 Apple says only the top-level object should be declared strong and all others as weak. The only top-level object in my view controller is the view. All other IBOutlets are subviews.
#2 From history — Before iOS 6, UIViewControllers used to remove views under low memory conditions. Remember viewDidUnload? Back then IBOutlets to any subview in the view hierarchy had to be declared as weak, otherwise, the view could not be unloaded due to strong references.
When unloading views was removed, the developer was now free to make IBOutlets weak, strong, assign, etc. The restriction that IBOutlets had to always be declared weak was no longer necessary. (the controller’s view hierarchy sticks around until the view controller is deallocated)
#3 “!” needs a guarantee that the view exists, so you should use strong to provide that guarantee.
Conclusion
According to my observation, you should go with “weak” because weak reference helps to prevent the reference cycle. The reference cycle leads to memory leaks and slows down our application.
However, to ensure the object alive and in memory, you need to make sure some other part of our app has a strong reference to the object. Yes, there is always a superview that ensures it. If you go to UIViewController's definition and see UIView is having strong reference and any IBOutlets will be a subview of it.
Go with Apple’s recommendation — use “weak”
Optional vs Implicitly unwrapped
#1 When you access an implicitly unwrapped optional(!), the system assumes it has a valid value and automatically unwraps it. However, it can be treated the same as optional now with some differences(see here).
#2 When a view controller is loaded from a storyboard, the system instantiates the view hierarchy and assigns the appropriate values to all the view controller’s outlets. By the time the view controller’s viewDidLoad() method is called, the system has assigned valid values to all of the controller’s outlets, and you can safely access their contents.
From the above pointers, it seems that you will have IBOutlets reference while using it, and you can use !. However, there can be risks of using ! with IBOutlets -
Risk#1, suppose you have one view controller and separate XIBs for iPad & iPhone devices. If you want to add a button on iPad and not on iPhone’s UI then optional will help you a lot. Otherwise, you need to add device checks while using that button.
Risk#2, case when accessing an outlet before its value is set. If you access an outlet before or while the view controller loads its view, you can run into a runtime error.
Conclusion
As per the discussion and Apple recommendation, you can go with “!” for convenience.
However, I suggest using optional for IBOutlets as well. There is no harm using it.
As per my suggestion use the below version(weak with optional). However, there can be different opinions also.
Happy coding!