Whenever we want to add an instance of this custom view to the visible screen, we now need to:
- load the Nib, and
- extract the actual view from the array of loaded objects (because we did not connect it to any outlet on the File’s Owner), and finally
- add the newly-instantiated custom view as a subview and set its frame.
Something like this:
MyCustomView customView = nil; NSArray* elements = [[NSBundle mainBundle] loadNibNamed: @”MyCustomView” // (1) owner: nil options: nil]; for (id anObject in elements) { // (2) if ([anObject isKindOfClass:[MyCustomView class]]) { customView = anObject; break; } } [self.view addSubview:customView]; // (3) customView.frame = CGRectMake(100.0, 100.0, 400.0, 90.0);
This is tedious because most of it is generic code that is repeated every time we instantiate a custom view from a Nib. Therefore, my colleague Michael moved all boilerplate code to a UIView category, resulting in the following class method:
// UIView+NibLoading.m
- (UIView) loadInstanceFromNib { UIView result = nil; NSArray* elements = [[NSBundle mainBundle] loadNibNamed: NSStringFromClass([self class]) owner: nil options: nil]; for (id anObject in elements) { if ([anObject isKindOfClass:[self class]]) { result = anObject; break; } } return result; }
With this category, the instantiation code becomes much sleeker:
MyCustomView* customView = [MyCustomView loadInstanceFromNib]; [self.view addSubview:customView]; customView.frame = CGRectMake(100.0, 100.0, 400.0, 90.0);