iosuiviewloadnibnamedinitwithframedesignated-initializer

loadNibNamed vs. initWithFrame dilemma for setting frame's height and width


I created a UIView subclass associated with .xib file. This UIView subclass is to be used in a UIViewController. In the controller, I think there are two options how we instantiate the UIView subclass:

MyUIView *myView=[[MyUIView alloc] initWithFrame:aRect];

and

MyUIView *myView = [[[NSBundle mainBundle] loadNibNamed:@"MyUIView" 
                                                  owner:self 
                                                options:nil] lastObject]; 

I prefer the first approach or its variants that allow me to perform custom initialization. The only problem is that I have to specify a frame's rect, which was already specified in .xib (I mean frame's height and width of MyUIView). Yes, I can hardcode it again in aRect, but this is tedious to maintain (e.g., when I change position of UIs in .xib, I have to update aRect, too).

So the second approach should come into mind as the frame rect is automatically set. The remaining problem is I cannot customize the initializer (say, I want to pass extra parameters during initialization).

What's your preference? Which one is better in your opinion?

EDIT1: Inspired by sergio's answer, I came out with this workaround:

// In MyViewController.m
MyUIView *myView=[[MyUIView alloc] initWithFrame:CGRectMake(x, y, 0.0, 0.0)];

// In MyView.m
- (id)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame]) {
        self = [[[NSBundle mainBundle] loadNibNamed:@"UnmovableTagView" 
                                              owner:self 
                                            options:nil] lastObject]; 
        [self setFrame:CGRectMake(frame.origin.x, 
                                  frame.origin.y, 
                                  [self frame].size.width, 
                                  [self frame].size.height)]; 
        // frame's width and height already determined after 
        // loadNibNamed was called
       ...
    }
    return self;
}

Solution

  • Have you tried using:

    MyUIView *myView=[[MyUIView alloc] initWithFrame:CGRectZero];
    

    I don't know if it works in your case (loading the view from a nib), but I use it successfully when I create my custom view programmatically.

    You can give it a try.

    EDIT:

    you could define your own init method for your view:

    -(id)initWithPosition:(CGPoint)pos;
    

    and then call:

    -(id)initWithPosition:(CGPoint)pos {
    
      if (self = [super initWithFrame:{pos,{0,0}}]) {
        self = [[[NSBundle mainBundle] loadNibNamed:@"UnmovableTagView" 
                                              owner:self 
                                            options:nil] lastObject]; 
        [self setFrame:CGRectMake(frame.origin.x, 
                                  frame.origin.y,  
                                  [self frame].size.width,    
                                  [self frame].size.height)]; 
         // frame's width and height already determined 
         // after loadNibNamed was called
       
      }