Support there are 2 views in the XIB file: UIView1, UIView2.
And the UIView1Owner is the owner of the UIView1. I guess when the XIB is loaded, it will automatically load the 2 views. However, the constructor (initWithFrame:) in the UIView1Owner will not be triggered.
It seems there is some magic behind the scene, and I am wondering how to add some stuff to the constructor of the UIView.
From the "initWithFrame:" section of http://developer.apple.com/library/ios/ipad/#documentation/uikit/reference/UIView_Class/UIView/UIView.html
If you use interface builder to design your interface, this method is not called when your view objects are subsequently loaded from the nib file. Objects in the nib are reconstituted and initialized using their initWithCoder: method...
Place any code you want in the initWithCoder: method.
initWithFrame will be called only for two created from xib objects (UIView1, UIView2). xib owner is assumed to exist before xib load.
Related
Here's the deal: I'm using the DEFacebookComposeViewController which is a custom subclass of a UIViewController. This subclass is using an xib to setup the user interface.
Now I want to add some additional GUI elements to DEFacebookComposeViewController so I figured I would create a subclass named something like MySubclassDEFacebookComposeViewController : DEFacebookComposeViewController and create a xib.
However the xib MySubclassDEFacebookComposeViewController.xib is not showing any of the GUI elements from DEFacebookComposeViewController.xib which I thought it would do since it's a subclass of that class.
So basically I'm just wondering what is the correct approach in adding new elements to a subclassed UIViewController and xib?
Copy the DEFacebookComposeViewController.xib and rename it to MySubclassDEFacebookComposeViewController.xib and edit it to your likings.
A UIViewController will look by default for a nib/xib with the same name (even without the controller part at the end) when created
From the docu of UIViewController:
If you use a nib file to store your view controller’s view, it is
recommended that you specify that nib file explicitly when
initializing your view controller. However, if you do not specify a
nib name, and do not override the loadView method in your custom
subclass, the view controller searches for a nib file using other
means. Specifically, it looks for a nib file with an appropriate name
(without the .nib extension) and loads that nib file whenever its view
is requested. Specifically, it looks (in order) for a nib file with
one of the following names:
If the view controller class name ends with the word “Controller”, as
in MyViewController, it looks for a nib file whose name matches the
class name without the word “Controller”, as in MyView.nib. It looks
for a nib file whose name matches the name of the view controller
class. For example, if the class name is MyViewController, it looks
for a MyViewController.nib file.
So you need to specify the nib you want to use or name it after the view controller. Since you want to add/modify the old nib you need a copy of it.
This is assuming that DEFacebookComposeViewController.xib does not have any IBOutlets by default. If it has you can modify the existing nib in viewDidLoad. Adding more subViews can always be accomplished aften the view is loaded regardless if there are IBOutlets.
I've gotten pretty comfortable using the viewDidLoad method to execute things I want done at the beginning of a view, but reading one of Apple's tutorials they set the data controller for the class in the awakeFromNib method and did nothing in the awakeFromNib. I swapped it and it seemingly worked identically in my app, but I'm not sure if it was better to have it in awakeFromNib or viewDidLoad.
When should I use either one?
awakeFromNib is called when the associated nib file with a class is loaded . Any class that can own a nib can use it. viewDidLoad is used only by view controllers. It is usually called when loading from nib as well but it can also be called by a view created in memory (very rare circumstance.). If you are using controllers, then I would suggest you to use viewDidLoad
For more Refer this Answer
viewDidLoad is associated with the view controller. If you need to initialize another control unarchived from the nib (e.g. UITableViewCell prototype) you cannot overload viewDidLoad, you need to overload awakeFromNib.
simple question,
If you're using a UIStoryboard, will UIViewController call awakeFromNib?
If not, what is the alternative method being called that we should use?
Cheers!
Yes, awakeFromNib will be called when using a UIStoryboard.
While a .storyboard file is a XML document, it will get converted to a set of traditional .nib files when you compile/package your app, so decoding those will be the same as in xib-based projects.
Yes, awakeFromNib is being called.
According to the documentation:
Initializing a View Controller Loaded from a Storyboard When you
create a view controller in a storyboard, the attributes you configure
in Interface Builder are stored in an archive. Later, when the view
controller is instantiated, this archive is loaded into memory and
processed. The result is a set of objects whose attributes match those
you set in Interface Builder. Here’s how that archive is loaded:
If your view controller implements an initWithCoder: method, that
method is called to process the information in the archive. If your
view controller does not implement an initWithCoder: method, your view
controller’s init method is called instead.
After the objects in the archive are loaded, iOS calls the awakeFromNib method on any objects
that implement such a method. You use this method to perform any
configuration steps that require other objects to already be
instantiated.
Yes awakeFromNib will be called when using a UIStoryboard.
In order to re-use a certain subview throughout my application (which is storyboard based), I decided to build the subview as a nib, and load it in. To do this, I have done the following:
I have a UIView subclass we can call Widget. I create a corresponding xib file, set the File owner property to my new subclass, hook up the IBOutlets.
Then, in my storyboard, I have a uiview inside of a view controller, and I set its class to the Widget class I created.
Within the widget class, I override initWithCoder, and in there load the nib as follows:
-(id)initWithCoder:(NSCoder *)aDecoder{
if ((self = [super initWithCoder:aDecoder])){
[self addSubview:[[[NSBundle mainBundle] loadNibNamed:#"Widget" owner:self options:nil] objectAtIndex:0]];
}
return self;
}
The app would crash at this point, and setting a break point here revealed that initWithCoder was being called over and over again.
It seems like I have mixed two methods for using a nib in this situation, but I'm unclear as to where I went wrong. I can throw up a stack trace if necessary, but it's basically endless nested calls to the same function.
Did you happen to set the View's "Custom Class" in your .xib file to "Widget"?
That would explain the behaviour you're seeing, because initWithCoder: is the initializer for all things loaded from a xib:
Your parent view, which contains a Widget object, is loaded from the xib
The Widget's initWithCoder: method gets called, and tries to load the Widget xib
The Widget xib contains a UIView with the Custom
Class "Widget", so again, a Widget object is being initialized with
initWithCoder:, etc.
If that is indeed the case, all you have to do is remove the "Custom Class" entry for the UIView in your Widget's xib.
I had same problem. My mistake was in empty File's Owner class. In File's Owner custom class must be NOT empty (Widget), and root view must be empty.
IBActions and IBOutlets were fine.
I thought that I should never call [super loadView] but something is confusing me.
In description of loadView (UIViewController Class Reference) it is said that "Your custom implementation of this method should not call super.",
but in ZoomingPDFViewer example that they gave, loadView implementation (ZoomingPDFViewerViewController) is calling [super loadView].
I have tried to call it from my loadView method and it works ok, but I just don't understand then what does it mean to not call super.
You definitely should not be calling [super loadView]. I'd say you found a bug in the ZoomingPDFViewer example.
You override loadView when you want to programatically create the view hierarchy for your view controller (not using a xib).
As you pointed out, the docs clearly state that you should not call super.
Your custom implementation of this method should not call super.
I assume this is to avoid loading both from a xib and programatically creating a view as this method is used by the base to load a view from a xib:
If the view controller has an associated nib file, this method loads
the view from the nib file.
Note also that even if during allocation of your UIViewController object you pass nil for the nibNameOrNil parameter that the UIViewController implementation of loadView will try to load any xib with the associated class name in it.
A view controller has an associated nib file if the nibName property
returns a non-nil value, which occurs if the view controller was
instantiated from a storyboard, if you explicitly assigned it a nib
file using the initWithNibName:bundle: method, or if iOS finds a nib
file in the app bundle with a name based on the view controller’s
class name. If the view controller does not have an associated nib
file, this method creates a plain UIView object instead.
The real intent of this method is to give you full control of building the view hierarchy without relying on the built in xib loading mechanism.:
You can override this method in order to create your views manually.
Personally, I override loadView if: 1.) The xib I would make for it is really trivial or 2.) The layout of the control is very dynamic, so creating a xib with a static layout has little benefit.
NSViewController tries to initialize a view from a nib in -loadView. Since your nib name is not set for your controller, it will just give you a self.view = nil; I would assume UIViewController works the same way.
So it should be safe, but you it's completely unnecessary.
If you dont have a view created in your IB, then you should call [super loadView] in your code to give a view to your program.
In case of your custom views, you are suppose to create a view with the interfaz builder, so you dont need to call it.
If you create your ViewController programmatically, you could call super.loadView() instead of self.view = UIView(frame: UIScreen.main.bounds) at the beginning of override func loadView().
However, do NOT call self.view before super.loadView(), since the former will trigger the latter if view did not been loaded.
I don't think it's a good idea to explain Apple's documentation like a robot.