views:

78

answers:

2

In my iPhone app, I made a custom UIView that I use in several different view controllers to display some information.

I'm familiar with making customer table cells for use in a table but I've never made a custom view again.

My question is what is the best way to load this view? I've tried simply placing the view in the view controllers I want it to appear in using IB, but that doesn't seem to be enough. It seems to me that it would make sense that if you set the Class Identity for the view that it should load up that view when the view controller is created. Or maybe it doesn't because it doesn't know what nib to get it from (it's in its own nib, of course).

Since it's not a view controller, I can't just use initWithNibName. I've tried using NSBundle loadNibNamed like I do with table cells but it seems like an awfully large amount of work. The code looks like this:

NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"MyCustomView" owner:nil options:nil];
for (id currentObject in topLevelObjects) {
    if ([currentObject isKindOfClass:[MyCustomView class]]) {
        self.customView = currentObject;
        break;
    }
}
[self.view addSubview:self.customView];

There must be an easier way which doesn't involve the loop. Also, creating the view this way makes me lose all the info from IB on where I actually placed the view. It's created at 0,0 which is not where I want it. Yes, I know I can set a new frame, but again, there must be an easier way. Is there a way I can do this all through IB? Or at least with less work programmatically?

+1  A: 

I also make it that way. I ran into the problem that I want to subclass UIView and using nib at the same time. I don't think there's better way to do so, because nib file can contains many objects and you have to specify which one to use. However, do it this way you can put IBOutlet in your MyCustomView and bind it in IB so the view can manage itself e.g. overriding layoutSubviews.

tia
What does IB actually do for me here? I have to manually load the view from the nib, and then manually set the frame so it is the correct position and size and then add it to the parent view. I've connected to the IB using a UIView object that I droopped into the designer but is that even really necessary? What is the IB doing for me here?
Mike
IB do all the subview layout for you, including those properties settings and IBOutlet and IBAction binding. You can continue finding the easier way, which I believe there is none. Anyway, your code snippet is good and if you make it a method, it will be easier for you to load custom UIView.
tia
+1  A: 

Try this: create a new UIViewController subclass (called ParentViewController for the sake of answer) that each of your controllers that need to display this information will then also subclass. This controller should not have a nib associated with it.

In ParentViewController, create an IBOutlet for a UIView that will hold a reference to a view containing your custom nib. (Called customView, again just because)

Now, open your nib (for the commonly used customView) in Interface Builder and select the File's Owner. Now in the Identity tab, choose the ParentViewController created above for the class. Now here comes the trick. In Connections, remove any connection to "view" (if there is any) and create a connection from the customView outlet to the topmost UIView of the nib that defines your customView.

Now, when you do a loadNibNamed in the code for a subclass of ParentViewController, it should automagically load the UIView from your nib and put a reference to it in the outlet for you to use. No loop required.

You could also add outlets for any other interface components in your nib and do the same thing.

Good luck!

coastwise
I tried following your instructions but I got lost. Here is what I did:
Mike
- I created an abstract UIViewController "parentViewController" and made it the parent class of the view controller than need my custom view.
Mike
- Now when you say "open your nib" which nib do you mean? The nib for the new parentViewController, the nib for the custom view, or the nib for each of my view controllers that need to use the custom view? I assumed you meant the nib for each of the child view controllers.
Mike
- I renamed the identity of the view to the name of the abstract parent. I dropped in a UIView element in to the layout window in the place I want it and connected "customView" to that UIView. It still shows up as a blank space though when the view controller is loaded. What am I missing? I even tried changing the identity of the UIView I dropped in to be the name of my customView class. How is it supposed to know what nib the custom view is loaded from?
Mike
I edited my answer in hopes of clarifying the solution."open your nib" refers to the shared custom view. The parentViewController shouldn't have a nib associated with it, as it is meant to be a generic controller.
coastwise
I'm not sure what you've renamed in your last comment, but I think you might be overthinking it. An exercise that will show you how this works: try creating a new subclass of UITableViewController (without a nib) and use the method described in my answer to populate the tableHeader with the contents of your custom nib. After loadNibNamed, do self.tableView.tableHeaderView = yourOutlet. Your custom view should now be the top of the tableview. This is how I first learned the technique.
coastwise