UIViewController Events

October 31, 2011

More often than not, I see novice MonoTouch developers get confused about what their ViewController is actually doing when they want to present it on the screen. This gets even more complex as we try to play nice with Apple’s definition of MVC and view presentation events.

###Loading vs Presentation vs Layout

In this tutorial, we’ll go over three things you might want to do in your ViewController’s Load, Present (and Push) and Layout methods. And more importantly, how UIViewController wants to manage them. It might seem convoluted (and it can be) but it will really prevent you from having ViewDidLoad methods with over 100 lines of code.

###Loading Views

Constructor: This is best to use when you’re using an interface builder and building your view from a nib file. I prefer to do things in code so I generally use loadView to initialize subviews.

LoadView: This is for when you’re manually initializing your ViewController.View subviews. Do not override this if you’re using Interface Builder. Make sure to call the base UIViewController implementation, but also remember that you don’t do any layout here because the view is not yet attached.

ViewDidLoad: This is often the default place for initialization, but not always the best. I often see this method get cluttered with initialization/RE-initialization and nil checks. It’s a good place to start, but generally should be reserved for stuff not related to the view.

###Presenting Views

ViewWillAppear: This is when the view is being presented onto the screen, but remember, it’s before any animations. So if you’re animating something on the screen, make sure and use the animated completion handler given to the PresentViewController in iOS 5. This is a bad place to do expensive tasks because you’re in the process of putting a container’s UIView on the screen, which is non-trivial operation.

ViewDidAppear: This is called when the view is added to a container inside the KEY window, which only really matters if you’re using multiple windows. I use this to update my views or make requests to the database or web service asynchronously and then callback to the main thread.

**NOTE:** these operations are idempotent, but not necessarily synchronous. Basically, you can't rely on them being called in order and only being called once when your view is presented. Again, View-related stuff should happen in specific operations, and calls made during presentation should have the associated state management.

###View Layout

NOTE: When laying out views, keep in mind that BOUNDS are the only thing that you can reliably make reference to, but you should be setting frame relative to its’ parent view container. Also, be mindful of your autoresizing mask, as it’s the only value that changes upon orientation change (weird, huh?).

In other words, Frame is a calculated value Bounds is a finite value

DidRotateFromInterfaceOrientation: Wait, this isn’t an explicit layout method?! Why did I bring this up first?!

Because this is where you’re most likely to get screwed with your frame & bounds, especially if you’re using CGAffineTransforms on your views during layout or if you don’t know much about UIViewAutoResizingMask.

Bottom line, just make sure that you reset your bounds here if you’re doing transforms / animations. And if you’re doing custom layout use this to detect changes in the bounds so you can adjust accordingly.

LayoutSubViews: This is called inside your UIView subclass, and is what you’d usually override when you have complex subviews that need to have specific layout. Pretty easy, but again be mindful of your UIViewAutoResizing mask here.

ViewDid / ViewWillLayoutSubViews: If you’re doing relative positioning, this is a place where you need to be aware of which method you are overriding. It can also be picky if you’re using iOS 5 custom containers.

Bottom Line? This is a great place to detect changes in your view hierarchy.

So, this is only a basic snippet of the sort of methods you’ll commonly use. Notice that I didn’t take heavy notice of any of the unload/disappear overrides. This would be an excellent thing to review, and especially if you’re debugging layout issues.

All the events and methods are described here in the Apple documentation. Feel free to ask any questions on Stack Overflow and I’d be glad to help out in anyway I can.

Comments

comments powered by Disqus