Question

For instance:

  1. Create a new UIVC using initWithNibName, using "nib-v1"
  2. Display it, e.g. using [(UINavigationController) nav pushViewController: myVC]
  3. Change the NIB that myVC is using to "nib-v2"

So far as I can see, this is the "correct" approach to app-design for a lot of apps, when paging through information where you need two slightly different UI screens for the info being displayed.

For instance, most of your pages are text, but some of them have an image too (think of an RSS reader, where some RSS entries have text + image, some are text only).

I've dealt with this previously by having one NIB file with a second, invisible, named UIView instance that I layered over the top of the first one, and switched on/off depending on on context, using the "hidden" flag.

But this is clearly wrong, and wastes memory.

However, I cannot see an obvious way to "reload" the view from the NIB file. I'm guessing I want to somehow reproduce the magic that initWithNibName does?

I suspect this is possible, but I'm sure that if you do it "the wrong way" then the app will simply crash horribly.

Was it helpful?

Solution

I agree with Rob, but if you really want to mess with swapping nib's (which is bad as it can easily lead to dangling pointers and the like), you could maybe load the view from the new nib with NSBundle's - (NSArray *)loadNibNamed:(NSString *)name owner:(id)owner options:(NSDictionary *)options method and do the view swapping yourself.

You should rather use different view controllers for different types of content. If they only differ slightly, you can still consider creating one base class and subclassing the different variations.

OTHER TIPS

You can always perform

[[NSBundle mainBundle] loadNibNamed:@"FileName" owner:viewController options:nil]];

but this will undoubtedly really mess things up, if you're not sure what you're doing, especially if view is connected in both of those nibs

You should redesign your view controller hierarchy to swap between two different controllers that load from two different nib files.


Alternately, you can have the controller manage swapping views that it loads from different files that are unrelated to it's nibName. In that case, you can load them in the above manner. And you will want to have their outlets (to, for example, subviewOne and subviewTwo) connected in different nibs.

You should check out the UINib class to see if it does what you want. It will allow you to load a nib file and keep it in memory.

But just to clarify: Do you want to modify the nib file itself? Or do you want to modify the contents of the nib file when it has been loaded into memory?

Off the top of my head, the first would be quite difficult (you can't modify the original file, since it is part of application bundle...maybe you copy it to Documents folder and write your own coder/decoder?) The second is easier, but I am not sure what the reason would be? Why not just modify the viewController/view after it has been loaded (in awakeFromNib, for example) and, if you want those changes to persist, save those changes to file afterwards.

In short, I don't know exactly what you would like to do, but the chances seem high to me there might be a better way to do it.

You shouldn't change what NIB file a UIViewController uses. Attaching the NIB to the UIViewController should be a one-time event. The hidden views are fine; they're certainly not clearly wrong. You can also programmatically add view elements after loading. If you're doing a lot of that, you can skip the NIB entirely and programmatically build the view in -loadView. Any of these are fine, but don't switch the NIB after initialization. I don't even recommend having multiple NIBs that you choose between for a given UIViewController class; it's just too confusing. Generally each NIB should map to a dedicated UIViewController class with a very similar (or identical) name.

In a related note, I recommend moving the name of the NIB into the UIViewController, as described in an earlier posting.

I came looking for an answer to the same problem, and ended up solving it like this:

UIViewController* ctrler = [[UIViewController alloc] initWithNibName:@"NewControllerNIB" bundle:nil];

// Replace previous controller with the new one
UINavigationController* nav = self.navigationController;
[nav popViewControllerAnimated:NO];
[nav pushViewController:ctrler animated:NO];

I'm not sure if it's possible the current controller gets deallocated before the call to push the new controller is executed, but so far it seems to work (until I just redesign the app with a better approach)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top