I'm trying to do something a bit elaborate, but something that should be possible. So here is a challenge for all you experts out there (this forum is a pack of a lot of you guys :) ).
I'm creating a Questionnaire "component", which I want to load on a NavigationContoller
(my QuestionManagerViewController
). The "component" is an "empty" UIViewController
, which can load different views depending on the question that needs to be answered.
The way I'm doing it is:
- Create Question1View object as a
UIView
subclass, defining someIBOutlets
. - Create (using Interface Builder) the
Question1View.xib
(HERE IS WHERE MY PROBLEM PROBABLY IS). I set both theUIViewController
and theUIView
to be of class Question1View. - I link the outlets with the view's component (using IB).
I override the
initWithNib
of myQuestionManagerViewController
to look like this:- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { if (self = [super initWithNibName:@"Question1View" bundle:nibBundleOrNil]) { // Custom initialization } return self; }
When I run the code, I'm getting this error:
2009-05-14 15:05:37.152 iMobiDines[17148:20b] *** Terminating app due to uncaught exception '
NSInternalInconsistencyException
', reason: '-[UIViewController _loadViewFromNibNamed:bundle:]
loaded the "Question1View" nib but the view outlet was not set.'
I'm sure there is a way to load the view using the nib file, without needing to create a viewController class.
For Swift user with designable option:
UIView
subclass and a xib files, that we will name after our own class name: in our case MemeView. Inside the Meme View class remember to define it as designable with the@IBDesignable
attribute before the class declarationRember to set the File’s Owner in the xib with our custom
UIView
subclass in Indetity Inspector panelIn the xib file now we can build our interface, make constraints, create outlets, actions etc.
We need to implement few methods to our custom class to open the xib once initialized
class XibbedView: UIView {
}
In our custom class we can also define some inspecatable properties to have full control over them from interface builder
@IBDesignable class MemeView: XibbedView {
}
Few examples:
If we need to add more information the view while is displayed inside a storyboard or another xib, to do that we can implement
prepareForInterfaceBuilder()
, this method will be executed only while opening the file in interface builder. If you did everything I wrote but nothing is working, the is a way to debug a sigle view by adding breakpoints in its implementation.Here is the views hierarchy.
Hope this helps a full sample can be downloaded here
To programmatically load a view from a nib/xib in Swift 4:
You can also use UIViewController's initWithNibName instead of loadNibNamed. It is simpler, I find.
Now you just have to create MySubView.xib and MySubView.h/m. In MySubView.xib set the File's Owner class to UIViewController and view class to MySubView.
You can position and size of the
subview
using the parent xib file.I had reason to do the same thing (programmatically loading a view from a XIB file), but I needed to do this entirely from the context of a subclass of a subclass of a
UIView
(i.e. without involving the view controller in any way). To do this I created this utility method:Then I call it from my subclass'
initWithFrame
method like so:Posted for general interest; if anyone sees any problems without doing it this way, please let me know.
I made a category that I like:
UIView+NibInitializer.h
UIView+NibInitializer.m
Then, call like this:
Use a nib name if your nib is named something other than the name of your class.
To override it in your subclasses for additional behavior, it could look like this:
There is also an easier way to access the view instead of dealing with the nib as an array.
1) Create a custom View subclass with any outlets that you want to have access to later. --MyView
2) in the UIViewController that you want to load and handle the nib, create an IBOutlet property that will hold the loaded nib's view, for instance
in MyViewController (a UIViewController subclass)
(dont forget to synthesize it and release it in your .m file)
3) open your nib (we'll call it 'myViewNib.xib') in IB, set you file's Owner to MyViewController
4) now connect your file's Owner outlet myViewFromNib to the main view in the nib.
5) Now in MyViewController, write the following line:
Now as soon as you do that, calling your property "self.myViewFromNib" will give you access to the view from your nib!