I have an xib for the main window, and I created a custom view in the following steps:
- Create a new class which inherits from
NSView
.
MyView.h
:
#import <Cocoa/Cocoa.h>
IB_DESIGNABLE
@interface MyView : NSTableCellView
@end
MyView.m
:
#import "MyView.h"
@implementation MyView
- (void)awakeFromNib {
NSLog(@"Post view awaking from nib.");
}
@end
- Create a new xib, and set the root view's class to the class created above. And design in that xib.
- Set outlets from the xib to the class.
And I tried to use this custom view in the main window in the following steps:
- Drag a custom view to the main window's xib.
- Set the class of that custom view to the class created above.
But nothing renders. From the log, I can see that code in awakeFromNib
from the custom view class is executed. When I set the class to be IB_DESIGNABLE
, the view gets empty in the main window's xib, different from what I designed.
I tried to set the file owner of the custom view's xib to the custom class, but nothing changed.
I guess the problem is that, the custom view's xib file is not actually loaded. When I googled it, there seem to be few references on this exact topic. So, how should I actually achieve this goal? I.e., design a view in IB, implement its methods in a class, associate these two, and expose it just like a system view for use in other xibs?
UPDATE:
I found a tutorial and realized what I lack (for correctly rendering the view when built). I have to add an outlet from the view in the xib to the view class:
@property (nonatomic, strong) IBOutlet NSView *view;
, and then load it in the (id)initWithCoder:(NSCoder *)coder
method.
[[NSBundle mainBundle] loadNibNamed:@"MyView" owner:self topLevelObjects:nil];
[self addSubview:self.view];
But the view still won't render in the interface builder.
You aren't providing any code, but here are some sanity checks:
Are you specifying the nib name correctly? In iOS its caps sensitive, but I don't think it is for you.
Check the package, is the nib actually there? Make sure it is part of the target you are building.
Could also be a frame issue. Make sure your auto-resizing parameters are set up correctly and that everything is in frame.
Another check you can do is set your IBOutlets to the actual frame of a UIView (or other) that you are interested in. Then in awakeFromNib, you can make sure their frame exists, or that they exist at all.
Your guess is correct: the xib is not being loaded. The nib loader doesn't know about your custom view's nib. The nib framework doesn't provide a facility for defining that connection, so you need to write code to load the xib.
Here's what I'd do. Add a
contentView
property to your custom view:In your custom view's nib, set the custom class of the root view back to
NSView
and disconnect all the (no-longer-valid) outlet connections from it. Set the custom class of File's Owner to your custom class name (e.g.MyView
). Connect the root view to File's Owner'scontentView
outlet, and connect all the other outlets from File's Owner to the appropriate objects in the nib.Then implement
awakeFromNib
in your custom view subclass to load the nib and add the content view as a subview:Note that you have to be careful not to allow infinite recursion. When your app loads the main window's nib, it will create an instance of
MyView
and (eventually) send itawakeFromNib
. Then, inawakeFromNib
,MyView
loads its own nib, where it is the File's Owner. The nib loader sendsawakeFromNib
to File's Owner, and this will happen while you're already in-[MyView awakeFromNib]
. If you don't check for this, you get a stack overflow due to unbounded recursion.