I have a navigation based application with two levels, in the second level the user select an option which should cause initialization and loading of the proper Nib file (there is a Nib file for every available selection).
Now I'm doing the initialization in a switch, based on the user selection.
The problem is that I'm adding Nibs as I going through the development, and now I need to update the switch part for every Nib I add.
I would like to create a *.plist file with the Nib names and to load the Nib according to a value in the plist file, I didn't managed to create a class with a value in a nsstring variable.
Here is one of my tries- Nib name is nsstring with the nib name value.
[code]
childController = [[Nibname alloc] initWithNibName:#Nibname bundle:nil];
[/code]
any help will be appreciated
Thx
Since we're talking about pushing view controllers here, you could generalise your 'alloc', and use the nibname to load the correct nib. Like this:
// load info from your plist into a dictionary
NSString * path= [[NSBundle mainBundle] pathForResource:#"AllNibs" ofType:#"plist"];
NSDictionary * nibs = [NSDictionary dictionaryWithContentsOfFile:path];
// use a value to select the right nib name
NSString *selector = #"viewController1";
NSString *nibName = [nibs objectForKey:selector];
// create the view controller from the selected nib name
UIViewController *aController = [[UIViewController alloc] initWithNibName:nibName bundle:nil];
Even if you've subclassed UIViewController, this will still load the correct class from the nib name you provide.
Related
I've a nib file in which i added 2 views. Now, i want to initate(init) my second view in my code, because i show it again and again after initate. so when i try to load nib file like:
UINib *nib = [UINib nibWithNibName:#"Taxi_Login_View" bundle:nil];
NSArray *nibArray = [nib instantiateWithOwner:self options:nil];
UIView *alert = [nibArray objectAtIndex: 1];
I get second view successfully after initate. But my first view also initate that i don't want. I just want to initate second view not first. Now what i do for this.
The instantiateWithOwner: will call the initWithCoder: of all view in the nib file.
Since you are instantiate a nib file not views with in your NIB file, all object declared in the NIB will be loaded.
If you do not want this then you will need to create separate nibs for both views.
I am in the process of developing an IOS rpg. This game is a controlled by a tab bar, and every view controller in the tab bar will have a common "header" that sits at the top of the screen and shows information about the player.
The rest of the screen, however, will show one of many different views. Each view controller will be responsible for showing multiple different "views" underneath the "header" view. In addition, many of these views will need to be scrollable, as they will not fit in the confines of the screen.
Questions:
1)How do you add two views from separate nibs to a single view controller.
2)How do you embed only one of those views in a scroll view.
Thank you.
You can load a nib through the loadNibNamed:owner:options: function on a NSBundle. What it will return is an array of all the objects in the nib (the list you see on the left when you create a nib in interface builder). If you're view is the first item on the list of objects in the nib, then its the object at the 0th index of that array.
NSArray *objects1 = [[NSBundle mainBundle] loadNibNamed:#"View1Nib" owner:self options:nil];
UIView *customView1 = [objects1 objectAtIndex:0];
NSArray *objects2 = [[NSBundle mainBundle] loadNibNamed:#"View2Nib" owner:self options:nil];
UIView *customView2 = [objects2 objectAtIndex:0];
UIScrollView *scroll = [[[UIScrollView alloc] init] autorelease];
[scroll addSubview:customView2];
[[self view] addSubview:customView1];
[[self view] addSubview:scroll];
If I have multiple views in a nib I make use of the restoration identifiers rather than relying on the order of the array and perform the following:
UINib *nib = [UINib nibWithNibName:#"Nib" bundle:nil];
NSArray* views = [nib instantiateWithOwner:self options:nil];
assert(views.count == 3);
UIView *aView;
UIView *anotherView;
UIView *yetAnotherView;
for (UIView* view in views) {
if ([view.restorationIdentifier isEqualToString:#"AViewId"]) {
aView = (SettingsCell *) view;
}
else if([view.restorationIdentifier isEqualToString:#"AnotherViewId"]) {
anotherView = (SettingsCell *) view;
}
else if([view.restorationIdentifier isEqualToString:#"YetAnotherViewId"]) {
yetAnotherView = (HeaderView *)view;
}
}
assert(aView && anotherView && yetAnotherView);
When you make a view controller, if you choose to generate an xib automatically, its view outlet will, by default be connected to a view. Now, create a new xib, with some different name, and make its files owner as your view controller class. Also, manually connect the view outlet.
Now, call the init method:
YourViewController *x = [[YourViewController alloc] initWithNibName: #"yourNibName" bundle:nil];
according to whatever xib you want to load, place the name instead of "yourNibName". Hope that helps.
You'll need to have references to both views, and you can simply [view addSubview:secondView]; as normal. As for how you get a reference to the views in the xib that is not associated with your view controller, there are several ways, but which you choose will depend on whether that view is already instantiated elsewhere in the app. I'm betting you're already instantiating that view elsewhere, and you simply want to add it. If it were me, I would use a singleton for that view's parent, so I could do something like:
[view addSubview:[ParentClass parentClassSharedInstance] viewToAdd]];
Scroll views are a beast you'll need to work with to fully understand, but you add views to them just like any other view. The important bit is that they have a contentSize property that can be bigger than their frame's size. I usually use a single view of the size I want to manage all views underneath the ScrollView. Good luck!
I found similar question here: How to load a UIView using a nib file created with Interface Builder.
But my problem is a little different. I need to load my custom view into 2 or 3 different UIViewControllers. Here is there answer that I like https://stackoverflow.com/a/4055353/602011 But I cannot set for myViewXib FileOwner three UIViewCOntrollers together. How to be?
In IB, you can set the FileOwner class type to UIViewController, then load the NIB using NSBundle's loadNibNamed:owner:options: method and iterate through the objects returned in order to modify or reference any child UIViews in the NIB.
NSArray* topLevelObjects = [ [ NSBundle mainBundle ] loadNibNamed:"bla"
owner:self
options:nil ] ];
for( id object in topLevelObjects )
{
if( [ object isKindOfClass:[ UILabel class ] ] )
{
UILabel* label = ( UILabel* ) object;
label.text = #"This is My Label Now!";
}
}
If you want to have one single xib file as the xib for several view controllers, so that basically all controllers have the same outlets, but different internal logic, I'd say you can create a base class with the outlets, set IB to use that class in the xib, then inherit your other controllers from that one.
That way you can load you generic view and have it connected with your more specific controllers. But that will only work if it is exactly the same xib for all the controllers.
This is based on that I imagine you want to do something like this:
AViewController *c1 = [[AViewController alloc] initWithNibName:#"MyXib" bundle:nil];
BViewController *c2 = [[BViewController alloc] initWithNibName:#"MyXib" bundle:nil];
I want to avoid laying out a view programmatically.
I want to only use a NIB file to do such work.
The problem is that the only way that I know of bringing a NIB file to life is via a controller like so:
ZBarReaderViewController* reader = [[ZBarReaderViewController alloc] init];
ScannerOverlayViewController *sovc =
[[ScannerOverlayViewController alloc] initWithNibName:#"ScannerOverlayView" bundle:nil];
reader.cameraOverlayView = sovc.view;
But this approach doesn't work out so well because stepping through the debugger shows that the views is 0x0 or Nil.
Now this may be because the controller is never added-to/displayed-on the view hierarchy and I'm trying to get a view out of it in order to recycle it as an "overlay view" on another controller that allows me to specify it.
Any thoughts on how this can be accomplished without writing the View programmatically?
You can load view from XIB file:
// I assume, that there is only one root view in interface file
NSString *nibName = #"CustomView";
NSArray *loadedObjects = [[NSBundle mainBundle] loadNibNamed:nibName owner:nil options:nil];
UIView *view = [loadedObjects lastObject];
I'm trying to load a NIB based on a variable I get from my settings file. This is the code:
//select the right nib name
NSString *nibVar = [nibs objectForKey:#"controller"];
// create the view controller from the selected nib name
UIViewController *aController = [[UIViewController alloc] initWithNibName:nibVar bundle:nil];
aController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:aController animated:YES];
[aController release];
This unfortunately does not work.
Any ideas here?
Thanks
You cannot instantiate "UIViewController" with arbitrary NIBs, you have to instantiate "[whatever your custom view controller class is]" with the NIB for that class.
It's crashing because it's trying to access properties that don't exist in UIViewController.
If you want to do this kind of dynamic view-controller loading, you need to do a bit more work, and use the special Class class method that lets you instantiate an object using a string for the class name, instead of hard-coded.
Sometehing like:
Class viewControllerClass = NSClassFromString( nibVar );
UIViewController* aController = (UIViewController*) [[viewControllerClass alloc] initWithNibName:nibVar bundle:nil];
Make sure the NIB name is correct and does not include the xib extension. It is also case sensitive.