1

Normally, I create custom UIViews by overriding drawRect. Is it possible to create a custom UIView that has a nib associated with it? (not asking about creating a custom UIView from a nib). Or is this usually done with a second view controller that gets contained in the first?

I'd still like to be able to call initWithFrame to instantiate it.

thx

EDIT #1 I'd like to have custom actions associated with buttons on it etc.... Is this functionality only capable in a VC or could a custom view work?

3
  • What's the difference whether you create a custom UIView and associate it with nib (suppose you can do it) or load a custom UIView from a nib? Commented Jul 6, 2013 at 23:45
  • like set the Custom Class in the inspector and then do loadNibNamed? Honestly, I do very little iOS programming. Is that the standard way people do it? I was kinda getting lost by different techniques. Commented Jul 6, 2013 at 23:50
  • Yes, it is a common practice. Commented Jul 7, 2013 at 0:10

2 Answers 2

1

It's hard to achieve exactly what you are after. Using nib is one way to load views, the other is to create them programatically.

So, trying to answer you questions:

  1. Yes, it is possible to associate a nib with a custom view through the Identity Inspector in IB. However, this is also "creating a custom UIView from a nib". Is that not what you are looking for?
  2. You do not have to use view controller containment to load views from nibs.
  3. Being able to call initWithFrame: is not part of using nibs at all since nibs need to use an NSCoder and are inflated from disk. -initWithCoder: should be used instead.
  4. Yes, you absolutely can have custom views in a nib respond to events from their subviews (UIButtons etc.). You would hook up the IBActions to the custom view subclass as normal. This is not exclusively part of a view controller, although according to MVC this might be breaking a "rule".

Loading a custom view from a nib is strait forward.

Create a strong property for your custom view (In your view controller is a good place)

@property (strong, nonatomic) BBCustomView *customView;

Then to instantiate it:

self.customView = [[[NSBundle mainBundle] loadNibNamed:@"View" owner:nil options:nil] lastObject];

At that point initWithCoder will be called on the custom view. Then you can add that custom view into an existing view hierarchy as normal.

Don't forget to set the proper class for the custom view in the nib file.

Hopefully that clears things up a bit!

Sign up to request clarification or add additional context in comments.

1 Comment

thx for answer, this will raise other questions but a good starting point
1

Yes, you can do it, but beware nib files are stored on disk instead of in RAM so it is ~10,000 times slower than not using a nib. If you are creating a lot of views, don't do it this way.

Basically your init method loads the nib file, grabs the view in the nib (which should be defined as the same class), and the instead of returning self like most init methods, it returns the view in the nib.

If you lookup the language documentation you will see it's common for an init method to return a different object than "self".

If you are not using ARC, you must release self and retain the view you are returning.

Here is how I would implement it (nib file must match the class name):

- (instancetype)initWithFrame:(CGRect)frame
{
  if (!(self = [super initWithFrame:frame]))
    return nil;

  NSArray *loadedObjects = [[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class]) owner:nil options:@{}];
  id newView = nil;
  for (id loadedObject in loadedObjects) {
    if ([loadedObject isMemberOfClass:[self class]]) {
      newView = loadedObject;
      break;
    }
  }

  // if ARC is disabled, you must do this:
  // [self release];
  // [newView retain];

  self = newView;

  self.frame = frame;

  return self
}

2 Comments

so how do I associate the nib with the custom view? do I need to do loadNibNamed in the subclass of UIView or is this called in the controller that wants to instantiate this custom view?
I would either do it in the subclass of UIView. Everything should be inside the init method.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.