Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Loading .xibs into a UIView

Tags:

iphone

uiview

I have a UIViewController with its own .xib, and I want to use a UISegmentedControl to display different information on the bottom half of the screen. I created a UIView in the container's .xib and connected it to a UIView property called detailView in the container's UIViewController.

I then created three .xib files in IB, one for the view that each segment needs to display in the detailView area.

I'm now stuck because I don't know how to load and unload the appropriate .xib file into the detailView area. Here's where I am:

- (void)segmentValueChanged:(id)sender {
    switch ([sender selectedSegmentIndex]) {
        case 0:
            // Unload whatever is in the detailView UIView and 
            // Load the AddressView.xib file into it
            break;
        case 1:
            // Unload whatever is in the detailView UIView and 
            // Load the ContactsView.xib file into it
            break;
        case 2:
            // Unload whatever is in the detailView UIView and 
            // Load the NotesView.xib file into it
            break;
        default:
            break;
    }
}

So how do I fill in the blanks and unload/load the detailView UIView properly?

Thanks!

--UPDATE--

The code in viewDidLoad is now: - (void)viewDidLoad { [super viewDidLoad];

    // Set the default detailView to be address since the default selectedSegmentIndex is 0.
    NSArray *nibObjects = [[NSBundle mainBundle] loadNibNamed:@"AddressView" owner:self options:nil];
    // assuming the view is the only top-level object in the nib file (besides File's Owner and First Responder)
    UIView *nibView = [nibObjects objectAtIndex:0];
    self.detailView = nibView;

    self.detailContainerView.autoresizesSubviews = YES;
    [self.detailContainerView addSubview:self.detailView];

    NSLog(@"self.view is %@", self.view);
    NSLog(@"self.detailContainerView is %@",self.detailContainerView);
    NSLog(@"self.detailView is %@", self.detailView);
}

And the debugger messages are:

self.view is UIView: 0x3a24d80; frame = (0 0; 320 460); autoresize = RM+BM; layer = CALayer: 0x3a35190
self.detailContainerView is UIView: 0x3a1aea0; frame = (20 57; 280 339); autoresize = W+H; layer = CALayer: 0x3a36b80
self.detailView is UIView: 0x3a24d80; frame = (0 0; 320 460); autoresize = RM+BM; layer = CALayer: 0x3a35190

Thanks!

like image 374
Neal L Avatar asked Jan 22 '10 22:01

Neal L


2 Answers

Use NSBundle's loadNibNamed:owner:options:. It returns an array of all top-level objects in the NIB file, which you can then assign to your ivars. If you need to distinguish between multiple objects in the array, give each one a unique tag in IB.

Try this:

case 0:
    [[NSBundle mainBundle] loadNibNamed:@"AddressView" owner:self options:nil];
    break;
...

If you have specified your view controller as File's Owner for AddressView.xib in Interface Builder, and have connected the view in the XIB to the view controller's detailView outlet, then the connection between the view and self.detailView should be in place after the call to loadNibNamed (because you specified self as the owner).

If that doesn't work, try something like this:

case 0:
    NSArray *nibObjects = [[NSBundle mainBundle] loadNibNamed:@"AddressView" owner:self options:nil];
    // assuming the view is the only top-level object in the nib file (besides File's Owner and First Responder)
    UIView *nibView = [nibObjects objectAtIndex:0];
    self.detailView = nibView;
    break;
...

Do the same for all cases in the switch statement. If you have declared detailView as @property (retain), the self.detailView = ... assignment will take care of releasing any formerly loaded views. There's no need to specifically unload the NIB contents.

like image 163
Ole Begemann Avatar answered Oct 19 '22 06:10

Ole Begemann


Basically you need to use UIViewController's initWithNibName to do what you want:

UIViewController *aViewController = [[UIViewController alloc] initWithNibName:@"AddressView" bundle:nil];
[self.detailView addSubview:aViewController.view];
[aViewController release];  // release the VC

In your AddressView xib, set the File's Owner class to UIViewController. The view's class should be the custom AddressView class.

This way you can position and size the subview using the main xib file. Then use the subview's xib to layout the controls.

like image 39
Ying Avatar answered Oct 19 '22 07:10

Ying