10 Minutes of Code: Overriding UIViewController's loadView

I’ve really been focusing on building programmatic views lately, and one way of avoiding the Massive View Controller problem is by creating a subclass of UIView and overriding the mechanism in which a UIViewController loads its view. In this way the subviews and constraints setup can be extracted out of the UIViewController. By overriding the loadView view controller lifecycle hook, you can initialize the view with a custom subclass.

The Apple documentation does say you shouldn’t do this unless you are implementing a view manually, which is exactly what I’m doing. However, accomplishing this may not be that intiutive, so I’d like to demonstrate exactly how to do this.

Defining the hook

Keep in mind in Swift, since you are overriding a method in the parent class, you’ll need to prefix the hook with the override keyword.

override func loadView() {
  ...
}

And in Objective-C we simply have:

- (void)loadView {
  ...
}

Initialize and Assign the View

You’ll need to provide the frame for your custom view, which we can grab from the UIScreen.main bounds.

In Swift, you’ll notice that I used a lazy property to create my view before assigning it in loadView. This is because when interacting with the view after this, you’ll need to reference the myCustomView instance to avoid typecasting the view property every time you call it.

override func loadView() {
  view = myCustomView
}
...
lazy private(set) myCustomView: MyCustomView = {
  return MyCustomView(frame: UIScreen.main.bounds)
}()

In Objective-C, you can accomplish the same thing by creating a property to override the parent view property. This will typecast the view property itself, so you can call it with self.view everywhere else you need to.

@interface MyCustomViewController ()
@property (nonatomic, strong) MyCustomView *view;
@end
@implementation ZZACalendarEntryPickerViewController
...
- (void)loadView {
   self.view = [[MyCustomView alloc] initWithFrame: [UIScreen main].bounds];
}
...
@end

Dynamically Initializing the View

One final thing to note, in Objective-C you’ll see a warning on the view property declaration.

Auto property synthesis will not synthesize property 'view'; it will be implemented by its superclass, use @dynamic to acknowledge intention

Make sure inside your @implementation to add @dynamic view; to silence this warning.

Thanks for reading, I hope this was useful!