0

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.

Adam
  • 32,900
  • 16
  • 126
  • 153
  • 2
    Please explain what you are trying to achieve what what problems you are running into. That will help us greatly to give you answers. – sosborn Sep 15 '11 at 01:13
  • Switching views from nib files can be heavy. I'd suggest loading one nib file and switching between views already loaded in that nib. – sudo rm -rf Sep 15 '11 at 01:26

5 Answers5

7

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.

bshirley
  • 8,217
  • 1
  • 37
  • 43
4

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.

Matthew Gillingham
  • 3,429
  • 1
  • 22
  • 26
  • Basically what I am trying to do is slide the views and subviews of two UIViewControllers around on the screen. I used the nib files to make design easier. However, I need the variables to keep certain values, so all I want to do is load a different nib to change the layouts. – Chad Sep 15 '11 at 01:38
  • _i think_ he's saying he want to change the active view hierarchy, not the nib files – bshirley Sep 15 '11 at 01:38
  • exactly what I was thinking - why throw away? the xib doesn't change and use UINib to handle the caching, low memory etc... – bryanmac Sep 15 '11 at 01:39
  • By saying that you are "moving the view controllers are around the screen" and that need the "variables need to keep certain values" are you saying something like, "the user can reposition the views on the screen and I want those positions to be saved, even after the application has terminated and been reloaded?" – Matthew Gillingham Sep 15 '11 at 01:54
  • With iOS 5, most of what I was trying to do, which was necessary but difficult, has been "fixed" by the new View Container classes Apple has added. – Adam Apr 04 '12 at 16:24
2

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.

MrMage
  • 7,282
  • 2
  • 41
  • 71
  • "which is bad as it can easily lead to dangling pointers" -- do you know of any specific examples of how this could happen? I'm assuming that a 100% correct approach *might* be to re-write Apple's NIB-loading code (which uses introspection, AFAICS) - since it already walks the object tree, it would prevent any such problems - no? yes? I'm thinking of trying this, but I don't know how much trouble I'm letting myself in for :) – Adam Jan 09 '10 at 17:18
  • I've been using this technique for a while now on different projects, and it's consistently worked fine. I never encountered problems with dangling pointers. – Adam Aug 10 '10 at 15:38
  • 1
    NB: this answer was best at the time, but now that iOS4 is around, UINib is a better way to do the same thing - see Matthew's answer below – Adam Apr 04 '12 at 16:23
0

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)

inolasco
  • 685
  • 8
  • 14
  • Yep, if you've got a Nav controller, AND you don't care about deleting the UIViewController (NB: I did care - I don't want to delete my controller, I want to change its UIView's. The ViewController has state that matters!), then the whole thing is easy. But 90% of cases you don't have that. – Adam Apr 04 '12 at 16:17
0

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.

Community
  • 1
  • 1
Rob Napier
  • 286,113
  • 34
  • 456
  • 610
  • Thanks, but loadView defeats the purpose of using NIB files, so that doesn't help here. I work with teams of non-programmers, who need to edit GUI's, so that we have to use NIB files for everything. (which works well, most of the time, until you run into situations like this where Apple's lack of foresight kicks in. Sadly, these situations are a bit more common than I'd hoped :( ). – Adam Jan 09 '10 at 17:16