Loading UIView from xib, crashes when trying to ac

2019-02-06 20:54发布

问题:

I have a xib-file with a small UIView on it, which in turn contains some labels. Now, I'm trying to load that UIView into an existing UIViewController, and change one of the label-texts. The reason I want to do it this way, is that the UIView will be reused with different label-texts so I figured making a custom class and loading it from a xib would be the best way to go.

I have tried several ways of loading it and I've successfully displayed it on my viewcontroller. The problem is, once I try to actually link an IBOutlet in Interface Builder, and access it, my app crashes.

I have created a custom UIView class, which looks like this:

CoverPanel.h

@interface CoverPanel : UIView {

    IBOutlet UILabel *headline;

}

@property (nonatomic, retain) IBOutlet UILabel *headline;

@end

CoverPanel.m

@implementation CoverPanel

@synthesize headline;

- (id)initWithFrame:(CGRect)frame 
{
    self = [super initWithFrame:frame];
    if (self) 
    {
        // Initialization code.
        //
        self = [[[NSBundle mainBundle] loadNibNamed:@"CoverPanel" owner:self options:nil] objectAtIndex:0];
    }
    return self;
}

In the CoverPanel.xib, I have linked the UILabel to the headline outlet. In my viewcontroller, here's how I create the CoverPanel instance, and this is where it crashes:

CoverPanel *panelView = [[CoverPanel alloc] initWithFrame:CGRectMake(0,0,300,100)];

So far, so good. It displays the UIView exactly as it's layed out in the .xib. But as soon as I try to change the headline.text like so:

panelView.headline.text = @"Test";

it crashes with this error: Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIView headline]: unrecognized selector sent to instance 0x5c22b00'

It might be something tiny I'm overlooking, but it has been driving me insane for hours and hours so far. Does anyone have any idea?

回答1:

You reassigned your custom view's class to the view that lived in your xib. You don't need to do that because then what you got back was the view from the xib and you've just leaked your CoverPanel. So, simply replace your initializer:

- (id)initWithFrame:(CGRect)frame 
{
    self = [super initWithFrame:frame];
    if (self) 
    {
        // No need to re-assign self here... owner:self is all you need to get
        // your outlet wired up...
        UIView* xibView = [[[NSBundle mainBundle] loadNibNamed:@"CoverPanel" owner:self options:nil] objectAtIndex:0];
        // now add the view to ourselves...
        [xibView setFrame:[self bounds]];
        [self addSubview:xibView]; // we automatically retain this with -addSubview:
    }
    return self;
}