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.
Related
I've been struggling with this for a while and I think the solution is really simple, but I just can't get it right. I have a UIViewController, which has its view and now I would like to add a subview to it. Subview should be loaded from a nib. I've followed the steps described here, ie.:
1. Create MyView class which is a subclass of UIView
2. Declare IBOutlet properties in MyView
3. Make .xib file, where File Owner is set to UIViewController and View class set to MyView
4. Connect outlets
5. In MyViewController, viewDidLoad method :
NSArray *nibViews = [[NSBundle mainBundle] loadNibNamed:#"MyView" owner:self options:nil];
MyView *mView;
for (id view in nibViews) {
if ([view isKindOfClass:[MyView class]]) {
mView = (MyView*) view;
}
}
[self.view addSubview:mView];
mView is loaded successfully, but when I try to add it as a subview I get EXC_BAD_ACCESS. I've even added: mView = [(MyView*) view retain]; but that doesn't help.
What am I doing wrong?
Don't worry...
You don't need to take separate nib file and referencing to the myView class again. Simply you can drag UIView from library into your current viewController's xib, and then u can simply connect the view from current view to the xib.
See below images:
i'm not sure of your point 3:
Make .xib file, where File Owner is set to UIViewController and View class set to MyView
the file owner shouldn't be the uiviewcontroller, but the MyView class
In my case, I didn't want my view controller to have any knowledge of the IBOutlets from my view's .xib. I wanted my view subclass to own the IBOutlets. Unfortunately UIView doesn't have an initWithNibName: method, so I just created my own category.
Here's what I did:
In IB, click on your main UIView, and in the Identity Inspector, set the class to your subclass
In IB, click on File's Owner, and in the Identity Inspector, set the class to your subclass
Use your new category method initWithNibName: to instantiate your view.
And here's the category I created:
- (instancetype)initWithNibName:(NSString *)nibName
{
NSArray *arrayOfViews = [[NSBundle mainBundle] loadNibNamed:nibName owner:self options:nil];
if (arrayOfViews.count < 1) {
return nil;
}
self = arrayOfViews[0];
return self;
}
Inspired by this post.
Note though, that so far the frame will adjust automatically, so unlike the code in the post, I haven't yet had to explicitly set the frame.
Also, unlike the post's code, I needed to set owner:self so the IBOutlets would be wired up correctly.
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 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 have a nib file I'm trying to instantiate in code. My UIViewController's main view is also loaded from a nib file.
Here's my UIViewController's viewDidLoad method:
- (void)viewDidLoad
{
[super viewDidLoad];
UINib *nib = [UINib nibWithNibName:#"MyCustomView" bundle:nil];
NSArray *nibViews = [nib instantiateWithOwner:self options:nil];
MyCustomView *myView = [nibViews objectAtIndex:0];
myView.frame = CGRectMake(100.0f, 100.0f, 91.0f, 91.0f);
[self.view addSubview:myView];
}
This creates some sort of endless loop. If I comment out [self.view addSubview:myView], myView appears, but everything currently on the screen disappears. I didn't think instantiateWithOwner added the view to the screen. If it does, how do I get access to it?
Thanks for your help.
The instantiateWithOwner method reassigns the properties of your view controller (set from the nib the controller was created from) to ones from the new nib. Those properties likely include the view property, so that method, within it, contains a call to setView:, and sets the view controller's view to the new nib's view. Afterwards, you're trying to add a view as a subview to itself, and that, naturally, causes problems.
You want to create your own property, for instance, secondaryView, set the nib's view to that, and add it as a subview. You don't want to reassign your view controller's view.
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.