Recently I wrote some code where I tried to refer to an outlet on a UIViewController
I'd just instantiated with [storyboard instantiateViewControllerWithIdentifier]
and modify the subview that the outlet pointed to before presenting the ViewController
. It didn't work because the ViewController
's view hadn't loaded its subviews yet, including the one that my outlet referred to, so the property just gave me a null pointer.
After (with some struggle) tracking down the cause of my issue in the debugger, I Googled around and learned, through answers like this one, that I can cause the view to load its subviews without being displayed by calling the myViewController.view
getter. After that, I can access my outlet without any problems.
It's a clear hack, though, and Xcode - quite rightly - doesn't like it, and angrily protests with this warning:
Property access result unused - getters should not be used for side effects
Is there a non-hacky alternative way to do this that doesn't involved abusing the .view
getter? Alternatively, are there canonical/idiomatic patterns for this scenario involving something like dynamically adding a handler to be called as soon as the subviews are loaded?
Or is the standard solution just to replace myViewController.view
with [myViewController view]
to shut up Xcode's warning, and then live with the hack?
If you want to force a layout update, call the setNeedsLayout() method instead to do so prior to the next drawing update. If you want to update the layout of your views immediately, call the layoutIfNeeded() method.
layoutSubviews() This UIView method handles repositioning and resizing a view and all its subviews. It gives the current view and every subview a location and size. This method is expensive because it acts on all subviews of a view and calls their corresponding layoutSubviews methods.
loadView() When using Storyboards, this is the method that will load your nib and attach it to the view , but when instantiating view controllers manually, all this method does is create an empty UIView . You can override it to change this behaviour and add any kind of view to the view controller's view property.
On iOS 9 or newer, one can use:
viewController.loadViewIfNeeded()
Docs: https://developer.apple.com/reference/uikit/uiviewcontroller/1621446-loadviewifneeded
I agree that forcing a view to load should be avoided but I ran into a case where it seemed the only reasonable solution to a problem (popping a UINavigationController containing a UISearchController that had yet to be invoked causes a nasty console says warning).
What I did was use new iOS9 API loadViewIfNeeded and for pre-iOS9 used viewController.view.alpha = 1.0. Of course a good comment above this code will prevent you (or someone else) removing this code later thinking it is unneeded.
The fact that Apple is now providing this API signals it can be needed from time to time.
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