I make all my controllers in code and most of the GUI too. Some GUI's I make with IB. I then set the file's owner to the viewcontroller and drag an connection from the file's owner to the view. But initWithNibName confuses me...
I am override the designated initializer to this
- (id)init {
[super initWithNibName:nil bundle:nil];
return self;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
return [self init];
}
Why do I not need to set which nib the viewController shall use in the init-initalizer? Because it works without. I thought I must use [super initWithNibName:#"SomeNib" bundle:nil];
In the init-initalizer
From docs: If you specify nil for the nibName parameter, you must either override the loadView method and create your views there or you must provide a nib file in your bundle whose name (without the .nib extension) matches the name of your view controller class. (In this latter case, the class name becomes the name stored in the nibName property.) If you do none of these, the view controller will be unable to load its view.
It works without only if your nib name is the same as your controller class name. In that case Apple does some magic. It is generally good form to specify the nib name.
Related
The default init method signature on XCode-generated view controllers is:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil{ }
I've seen these initialized with both values supplied, just the nib name (with bundle as nil), or just nil as both. All seem to work.
How does the UIViewController really handle self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];? Is there a disadvantage to just passing in nil for both values?
If you pass nil as the nibName, the method will look for a nib with the same filename as your view controller.
For instance, if you have a view controller called MyViewController it will look for a MyViewController.xib nib file.
If no nib is found, you will need to override the loadView method to create and assign a UIView to the controller's view outlet.
- (void)loadView
{
UIView *theView = [[UIView alloc] ...
// Setup the main view
self.view = theView;
}
From the docs:
nibName:
If you specify nil for the nibName parameter and you do not override the loadView method, the view controller searches for a nib file using other means. See nibName.
nibBundle:
The bundle in which to search for the nib file. This method looks for the nib file in the bundle's language-specific project directories first, followed by the Resources directory. If nil, this method looks for the nib file in the main bundle.
I'm developing an iOS 4 application and I have developed some classes that I want to use in others projects.
One of this classes, called MapViewController, is a UIViewController subclass. This class uses a XIB file that I've created with interface builder.
I'm wondering if a use MapViewController in another project as a super class from a new class, How can I use it associated XIB?
I want to reuse MapViewController and its XIB, but I don't know if I have to do something special with the XIB file.
I don't know how to explain this. If you need more details, please tell me.
UPDATE:
I want to create a new class that inherit from MapViewController, like this:
...
#interface NewMapViewController : MapViewController {
...
And, now if I want to continue using the same XIB (the one from MapViewController), what must I do?
Since you are gonna inherit from MapViewController, your MapViewController becomes the super class. And you also have MapViewController.xib. It seems pretty straightforward to me if you use the initializer for NewMapViewController
NewMapViewController.m
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
NSLog(#"Subclass initWithNibName called");
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
Initialize your NewMapViewContoller like:
//Nib of super class is MapViewController
NewMapViewController *nmapController = [[NewMapViewController alloc] initWithNibName:#"MapViewController" bundle:[NSBundle mainBundle]];
I am a little curious, I have a view controller class and an NIB/XIB (both are named "MapViewController") If I do the following it loads the NIB with the matching name.
-(id)init {
self = [super initWithNibName:#"MapViewController" bundle:nil];
if(self) {
do things ...
}
return self;
}
if on the other hand I just specify [super init] does Xcode just look for a NIB that matches the name of the controller, is that how this is working?
-(id)init {
self = [super init];
if(self) {
do things ...
}
return self;
}
cheers Gary.
From the documentation:
If you specify nil for the nibName
parameter and do not override the
loadView method in your custom
subclass, the default view controller
behavior is to look for a nib file
whose name (without the .nib
extension) matches the name of your
view controller class. If it finds
one, the class name becomes the value
of the nibName property, which results
in the corresponding nib file being
associated with this view controller.
Yes, in this particular case it will work. According to the UIViewController, calling init is similar to calling initWithNibName:bundle: with nil as nib name:
If you specify nil for the nibName
parameter and do not override the
loadView method in your custom
subclass, the default view controller
behavior is to look for a nib file
whose name (without the .nib
extension) matches the name of your
view controller class. If it finds
one, the class name becomes the value
of the nibName property, which results
in the corresponding nib file being
associated with this view controller.
does Xcode just look for a NIB that
matches the name of the controller
Pretty much:
If you specify nil for the nibName
parameter and do not override the
loadView method in your custom
subclass, the default view controller
behavior is to look for a nib file
whose name (without the .nib
extension) matches the name of your
view controller class. If it finds
one, the class name becomes the value
of the nibName property, which results
in the corresponding nib file being
associated with this view controller.
I need to create my own UIView class and it is not something I have had to do. I created the class, then laid out the small view in IB (it's just a few labels that i will later need to add data to ). but now im stuck on how to actually put an instance of it in my main view. Can someone point me in the direction of a good tutorial? The closest thing I have done to this is creating a custom tableViewCell.
DataTagViewController.m:
- (id)initWithNibNamed:(NSString *)DataTagViewController bundle:bundle {
if ((self = [super initWithNibName:DataTagViewController bundle: bundle])) {
// Custom initialization
}
return self;
}
MapView.m:
DataTagViewController *dataTag = [[DataTagViewController alloc] initWithNibNamed:#"DataTagViewController" bundle:nil];
[theMap addSubView: dataTag.view]; <<< this line causes the crash (theMap is a UIView)
I now get this runtime error when adding the subview:-[UIView addSubView:]: unrecognized selector sent to instance 0x470f070'
2010-06-06 21:22:08.931
UIViewController is not a view, but controls a view. If your DataTagViewController class extends UIViewController, then you'll want to add it's view, not the class itself:
[theMap addSubView:dataTag.view];
Also, do you have a DataTagViewController.xib file created that has your view in it? If you don't, you'll need to create one and use the UIViewController's initWithNibName:bundle method. Otherwise, you'll have to implement the loadView method instead to provide your own view via code.
Edit
Your init function is using the name of your class as a variable. That probably won't work. Use the default sigature:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])
{
}
}
If you aren't doing anything beyond the init function, you don't need to implement this method. Your alloc/init statement is enough.
For a good tutorial, read the View Controller Programming guide in the docs.
What is the parent class of DataTagViewController? You say you need to create "my own UIView class", but your example suggests that you actually want to create UIViewController subclass. initWithNibNamed: is UIViewController method. If your parent is UIView, then "unrecognized selector" makes sense.
The App Delegate has an outlet property to the view controller, and the view controller is created in the nib.
Althoug the -viewDidLoad method of the view controller gets loaded, it seems that it designated initializer receives no call:
- (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle {
NSLog(#"iniwinib");
if (self = [super initWithNibName:nibName bundle:nibBundle]) {
// do stuff
}
return self;
}
I also tried with -init, but this also does not receive a call. No NSLog output. Is there another initializer that I must use in this case?
-initWithCoder: is the initializer in this case (because the object is being deserialized from the NIB), but the routine you actually want here is -awakeFromNib. That's what's called after all the objects in the NIB have been constructed and all the outlets have been wired.
Are you actually calling initWithNibName to create your ViewController somewhere in the code? If not then it will never get called, this method does not get called automatically you must call it to create your viewController from your nib. But you dont need to do call this method because you have already set the ViewController in the nib..