将IBOulets添加到自定义UIView子类崩溃'不符合键值'

时间:2017-04-19 13:52:04

标签: ios objective-c inheritance uiview

我创建了两个不同的子视图EPStudentProgressOpenQuestionEPStudentProgressMultipleChoiceQuestion。它们都继承自EPStudentProgressQuestion,因为它们的子视图共享一些共同的信息和行为。

每个视图都有自己的XIB文件。

EPStudentProgressQuestion内,有以下代码:

#import "EPStudentProgressQuestion.h"

@interface EPStudentProgressQuestion ()

@property (assign, nonatomic) EPStudentProgressQuestionType questiontype;

@end

@implementation EPStudentProgressQuestion

#pragma mark - UIView lifecycle

- (instancetype)initWityQuestionType:(EPStudentProgressQuestionType)questionType {
    self = [super init];

    if (self) {
        self.questiontype = questionType;

        [self setupView];
    }

    return self;
}

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];

    if (self) {
        [self setupView];
    }

    return self;
}

- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];

    if (self) {
        [self setupView];
    }

    return self;
}

#pragma mark - Private methods

- (void)setupView {
    NSBundle *bundle = [NSBundle bundleForClass:[self class]];
    UIView *view = [[bundle loadNibNamed:[self nibNameForQuestionType] owner:[self class] options:nil] firstObject];
    view.frame = self.bounds;

    [self.layer setCornerRadius:2.f];
    [self.layer setBorderWidth:1.f];
    [self.layer setBorderColor:[UIColor colorWithWhite:232/255.f alpha:1.f].CGColor];
    [self setClipsToBounds:YES];

    [self setTranslatesAutoresizingMaskIntoConstraints:NO];
    [self addSubview:view];
}

- (NSString*)nibNameForQuestionType {
    switch (self.questiontype) {
        case EPStudentProgressQuestionTypeOpen:
            return @"EPStudentProgressOpenQuestion";

        case EPStudentProgressQuestionTypeMultipleChoice:
            return @"EPStudentProgressMultipleChoiceQuestion";
    }
}

如您所见,非常简单的代码。

如上所述,每个EPStudentProgressQuestion视图都有自己的XIB文件,将Files Owner连接到Identity Inspector类。

这是EPStudentProgressOpenQuestion

#import "EPStudentProgressOpenQuestion.h"

@interface EPStudentProgressOpenQuestion ()

@property (weak, nonatomic) IBOutlet UILabel *lblQuestion;

@end

@implementation EPStudentProgressOpenQuestion

@end

EPStudentProgressMultipleChoiceQuestion只是没有任何IBOutlet完全相同。但是,只要我为其中任何一个视图创建IBOutlets,我就会收到错误... IBOutlet is not key-value compliant...

没有IBOutlets一切正常。每个视图都正确加载,并且它很好地放置在我想要的视图中。但是只要我将一些IBOutlets从XIB链接到相应的类,就会崩溃......

这是崩溃:

*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<EPStudentProgressQuestion 0x1020196b0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key lblQuestion.'

这就是我实例化EPStudentProgressQuestion视图的方式:

EPStudentProgressOpenQuestion *questionView = [[EPStudentProgressOpenQuestion alloc] initWityQuestionType: EPStudentProgressQuestionTypeOpen];
[self.vQuestionsContainer addSubview:questionView];

关于如何能够在没有问题的情况下链接IBOutlets的任何想法?

提前谢谢!!

修改

如果我按如下方式更改bundleowner类:

NSBundle *bundle = [NSBundle bundleForClass:[EPStudentProgressOpenQuestion class]];
    NSArray *views = [bundle loadNibNamed:[self nibNameForQuestionType] owner:[EPStudentProgressOpenQuestion class] options:nil];
    UIView *view = [views firstObject];

我收到了同样的错误,但我没有EPStudentProgressQuestion而是EPStudentProgressOpenQuestion错误...

编辑2: 测试项目链接:https://mega.nz/#!oBhWkawC!RSOzrPOfq_UTVWd3jraRkneuCIyIkS61PKGeca2Bilc

3 个答案:

答案 0 :(得分:0)

您的视图控制器可能在您的xib中有错误的类。请更改UIView类名称,而不是像文件

中的文件所有者

enter image description here

您还在:

中调用了[self setup]方法
- (instancetype)initWityQuestionType:(EPStudentProgressQuestionType)questionType {
    self = [super init];
    if (self) {
        self.questiontype = questionType;
        [self setupView];
    }
    return self;
}

您不需要再次拨打电话

- (instancetype)initWithFrame:(CGRect)frame {
} 

- (instancetype)initWithCoder:(NSCoder *)aDecoder {
}

它正在创建一个init循环并导致内存泄漏。

答案 1 :(得分:0)

您的崩溃表明EPStudentProgressQuestion(您的超类)不符合键值。这意味着在您访问IBOutlet时,您引用EPStudentProgressQuestion而不是EPStudentProgressOpenQuestionEPStudentProgressMultipleChoiceQuestion

只需检查您使用新IBOutlets的代码,并更改其中使用的变量类型或将强制转换添加到正确的类。

答案 2 :(得分:0)

让您崩溃的问题是,您正在传递[self class]而非self作为笔尖所有者。将你的笔尖加载线更改为:

NSArray *views = [bundle loadNibNamed:[self nibNameForQuestionType] owner:self options:nil];

你还有另一个问题,那就是你要两次加载笔尖。在initWityQuestionType:中,您拨打[super init]。你没有意识到的是-[UIView init]来电[self initWithFrame:CGRectZero]。因此,您最终会调用被覆盖的initWithFrame:,并调用setupView。然后,当它返回initWityQuestionType:时,也会调用setupView

我建议你完全摆脱initWithFrame:覆盖。