3

I externalized a component in a XIB file so I can reuse it in several different views. Now in my view controller I load the XIB-based UIView and add it to the current view through :

NSArray *views = [[NSBundle mainBundle] loadNibNamed:@"ThumbsPreviewView" owner:self options:nil];
_likePreview = [views objectAtIndex:0];
[self.view addSubview:_likePreview];

At first, I thought that it was not working... but actually it works but only put the root view (i.e. the container of all my graphical components, which is transparent) to my view.

So I need to put this kind of code (for every sub component) to make it work :

[self.view addSubview:_likePreview];
NSArray *subviews = _likePreview.subviews;
for(UIView * subview in subviews) {
    [self.view addSubview:subview];
}

This is very counter-intuitive, and moreover I think it does not create the view hierarchy that I would like.

I am sure there is a solution because I did the same kind of thing in a UITableViewController to load a custom table header from a XIB. Using the exact same XIB file in this situation loads everything properly. Here is the code :

-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    switch(section) {
        case 0: {
            NSArray *views = [[NSBundle mainBundle] loadNibNamed:@"ThumbsPreviewView" owner:self options:nil];
            _likePreview = [views objectAtIndex:0];
            return _likePreview;
        }
    }
    return [super tableView:tableView viewForHeaderInSection:section];
}

With the above code, everything is fine, I got the whole view (= root view container with all its content) as the header of my table section.

So the question is : what am I doing wrong in my first example ? How can I add all content (container + all content) to my parent UIView as a proper UIView hierarchy ?

EDIT : I need to precise that everything is organized in my XIB file in a single root UIView, as follows (I cannot post image) :

* Thumbs preview view
|_ Button
|_ Image View
|_ Image View
|_ Image View
|_ Image View
|_ Button
|_ Button
|_ Button
|_ Label

Thank you very much for your help !

Christophe

1 Answers1

3

One way to load your component is to store your components into a top UIView object (s. attached screenshot).


(source: mobypicture.com)

You can then load your nib as usual and use -addSubview: to add your components to the view hierarchy.

EDIT:

Loading the nib with

UIView *view = [[[NSBundle mainBundle] loadNibNamed:@"testView" owner:self options:nil] objectAtIndex:0];

and adding the view to the view hierarchy with

[self.view addSubview:view];

leads to the following view hiearchy:

(lldb) po [[self view] recursiveDescription]
(id) $1 = 0x088487b0 <UIView: 0x89595b0; frame = (0 0; 320 548); autoresize = W+H; layer = <CALayer: 0x8958b30>>
   | <UIView: 0x89755c0; frame = (0 0; 320 200); autoresize = RM+BM; layer = <CALayer: 0x8975080>>
   |    | <UIView: 0x8975620; frame = (200 20; 100 30); autoresize = W+H; layer = <CALayer: 0x8975680>>
   |    | <UIView: 0x8975700; frame = (20 20; 100 30); autoresize = W+H; layer = <CALayer: 0x8974ea0>>
   |    | <UIRoundedRectButton: 0x8975790; frame = (20 58; 73 44); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x8975890>>
   |    |    | <UIGroupTableViewCellBackground: 0x8976030; frame = (0 0; 73 44); userInteractionEnabled = NO; layer = <CALayer: 0x8976100>>
   |    |    | <UIImageView: 0x89768d0; frame = (1 1; 71 43); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x89770f0>>
   |    |    | <UIButtonLabel: 0x8977af0; frame = (36 22; 0 0); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x8977be0>>
   |    | <UIRoundedRectButton: 0x8978990; frame = (227 58; 73 44); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x8978a60>>
   |    |    | <UIGroupTableViewCellBackground: 0x8978a90; frame = (0 0; 73 44); userInteractionEnabled = NO; layer = <CALayer: 0x8978b10>>
   |    |    | <UIImageView: 0x8978b80; frame = (1 1; 71 43); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x8979230>>
   |    |    | <UIButtonLabel: 0x8978be0; frame = (36 22; 0 0); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x8978cd0>>
Glorfindel
  • 21,988
  • 13
  • 81
  • 109
mkalmes
  • 144
  • 1
  • 10
  • This is exactly what I have : – Christophe Fondacci Oct 16 '12 at 10:13
  • Please check my edited question. You can check by yourself, loading such a XIB and adding it through [self.view addSubView:loadedNib] will only load your root view and none of its children. – Christophe Fondacci Oct 16 '12 at 10:20
  • Loading the NIB is OK, the problem happens when adding it to the view : [self.view addSubview:_likePreview]; adds only the root view. I need to add every subview one by one : NSArray *subviews = _likePreview.subviews; for(UIView * subview in subviews) { [self.view addSubview:subview]; } – Christophe Fondacci Oct 16 '12 at 12:39
  • Like I said, make sure that your UIButtons and UIViews are direct siblings of your root-view element. Set a breakpoint after `[self.view addSubview:_likePreview];`. Then type into the debugger `po [[self view] recursiveDescription]` and add the output to your question. – mkalmes Oct 16 '12 at 13:23
  • Returning this exact same view in a UITableViewController "viewForHeaderInSection" method works perfectly (as shown in my last code snippet from my question), showing the full component (UIView + all subviews) as a header of a table section so I am sure that my XIB is OK and that every component is a child of the root subview I am loading. I only have 1 UIView in the loaded UIView array, my root view, then containing everything as its child. Again, it does not work when invoking addSubView. – Christophe Fondacci Oct 16 '12 at 13:32
  • You didn't posted the output of the `recursiveDescription`-call. – mkalmes Oct 16 '12 at 13:55
  • I recreated the XIB from scratch and now it works. I did not make the `recursiveDescription` call on my former XIB so I can't tell whether or not the hierarchy was correct, I suspect it was not. Now it is. This is a bit weird. Anyway thanks for your help, now I know the `recursiveDescription` debug trick ! – Christophe Fondacci Oct 16 '12 at 15:43