I'm familiar with most of the process of creating an XIB for my own UIView subclass, but not everything is working properly for me - it's mostly to do with the IBOutlets linking up. I can get them to work in what seems like a roundabout way.
My setup is this:
- I have MyClass.h and MyClass.m. They have IBOutlets for a UIView (called view) and a UILabel (called myLabel). I added the 'view' property because some examples online seemed to suggest that you need this, and it actually solved an issue where I was getting a crash because it couldn't find the view property, I guess not even in the UIView parent class.
- I have an XIB file called MyClass.xib, and its File's Owner custom class is MyClass, which prefilled correctly after my .h and .m for that class existed.
My init method is where I'm having issues.
I tried to use the NSBundle mainBundle's 'loadNibNamed' method and set the owner to 'self', hoping that I'd be creating an instance of the view and it'd automatically get its outlets matched to the ones in my class (I know how to do this and I'm careful with it). I then thought I'd want to make 'self' equal to the subview at index 0 in that nib, rather than doing
self = [super init];
or anything like that.
I sense that I'm doing things wrong here, but examples online have had similar things going on in the init method, but they assign that subview 0 to the view property and add it as a child - but is that not then a total of two MyClass instances? One essentially unlinked to IBOutlets, containing the child MyClass instantiated via loadNibNamed? Or at best, is it not a MyClass instance with an extra intermediary UIView containing all the IBOutlets I originally wanted as direct children of MyClass? That poses a slight annoyance when it comes to doing things like instanceOfMyClass.frame.size.width, as it returns 0, when the child UIView that's been introduced returns the real frame size I was looking for.
Is the thing I'm doing wrong that I'm messing with loadNibNamed inside an init method? Should I be doing something more like this?
MyClass *instance = [[MyClass alloc] init];
[[NSBundle mainBundle] loadNibNamed:@"MyClass" owner:instance options:nil];
Or like this?
MyClass *instance = [[[NSBundle mainBundle] loadNibNamed:@"MyClass" owner:nil options:nil] objectAtIndex:0];
Thanks in advance for any assitance.
The second option is the correct one. The most defensive code you could do is like this:
And call like this:
I'm assuming your MyClass is a subclass of
UIView
? If that's the case, then you need to make sure that theUIView
of your .xib is actually of MyClass class. That is defined on the third Tab on the right-part in the interface builder, after you select the viewAll you need to do is create the subview via
loadNibNamed
, set the frame, and add it to the subview. For example, I'm adding three subviews using myMyView
class, which is aUIView
subclass whose interface is defined in a NIB,MyView.xib
:So, I define
initWithFrame
for myUIView
subclass:So, for example, in my
UIViewController
, I can load a couple of these subclassedUIView
objects like so:I originally advised the use controllers, and I'll keep that answer below for historical reference.
Original answer:
I don't see any references to view controllers here. Usually you'd have a subclass of
UIViewController
, which you would then instantiate withThe NIB file,
MyClass.xib
, could specify that the base class for theUIView
, if you want, where you have all of the view related code (e.g. assuming that MyClass was a subclass ofUIView
).Here's one method that I use:
UIView
, this will be calledMyClass
ParentViewController
.MyClass
.MyClass
will be connected by click-dragging from View (not File's Owner). If you want to connect them to variables fromParentViewController
then click-drag from File's Owner.ParentViewController
you need to declare an instance variable forMyClass
.ParentViewController.h
add the following:Synthesize this in your implementation and add the following in your
viewDidLoad
method: