J'ai créé deux sous-vues différentes EPStudentProgressOpenQuestion et EPStudentProgressMultipleChoiceQuestion. Ils héritent tous deux de EPStudentProgressQuestion car ils partagent tous les deux des informations et des comportements communs.

Chacune des vues possède son propre fichier XIB.

À l'intérieur de EPStudentProgressQuestion, il y a le code suivant:

#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";
    }
}

Comme vous pouvez le voir, un code très simple.

Comme je l'ai dit plus haut, chaque vue EPStudentProgressQuestion a son propre fichier XIB, connectant le Files Owner via la classe Identity Inspector.

C'est EPStudentProgressOpenQuestion:

#import "EPStudentProgressOpenQuestion.h"

@interface EPStudentProgressOpenQuestion ()

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

@end

@implementation EPStudentProgressOpenQuestion

@end

Exactement la même chose pour EPStudentProgressMultipleChoiceQuestion juste sans IBOutlet. Mais dès que je crée IBOutlets sur l'une de ces vues, j'obtiens l'erreur ... IBOutlet is not key-value compliant...

Sans IBOutlets, tout fonctionne correctement. Chaque vue se charge correctement et elle est bien placée dans la vue que je souhaite. Mais dès que je lie certains IBOutlets du XIB à la classe correspondante, ça plante ...

C'est le crash:

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

Et voici comment j'instancie la vue EPStudentProgressQuestion:

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

Une idée sur la façon de pouvoir lier IBOutlets sans problème?

Merci d'avance!!

MODIFIER:

Si je change les classes bundle et owner comme suit:

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

J'obtiens la même erreur mais au lieu de EPStudentProgressQuestion j'obtiens l'erreur pour EPStudentProgressOpenQuestion ...

MODIFIER 2: Lien du projet de test: https://mega.nz/#!oBhWkkneuCIyIkS61PKGeca2Bilc" rel="nofollow noreferrer"> https://mega.nz/#!oBhWkkneuCIyIkS61PKGeca2Bilc" rel="nofollow noreferrer"> https://mega.nz/#!oBhWkkneuCIyIkS61PKGeca2Bilc" rel="nofollow noreferrer"> https://mega.nz/#!oBhWkkneuCIyIkS61PKGeca2Bilc" rel="nofollow noreferrer"> https://mega.nz/#!oBhWkknawc!

0
Leeroy Jenkins 19 avril 2017 à 16:52

3 réponses

Meilleure réponse

Le problème qui vous bloque est que vous passez [self class] au lieu de seulement self comme propriétaire de la pointe. Changez votre ligne de chargement de plume comme suit:

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

Vous avez un autre problème qui est que vous chargez la pointe deux fois. En initWityQuestionType:, vous appelez [super init]. Ce que vous ne réalisez pas, ce sont les -[UIView init] appels [self initWithFrame:CGRectZero]. Vous finissez donc par appeler votre initWithFrame: remplacé, qui appelle setupView. Puis quand il revient à initWityQuestionType:, cela appelle aussi setupView.

Je vous recommande de vous débarrasser entièrement de votre remplacement initWithFrame:.

0
rob mayoff 19 avril 2017 à 15:49

Votre plantage indique que EPStudentProgressQuestion (votre superclasse) n'est pas compatible avec les valeurs-clés. Cela signifie qu'au moment où vous accédez à l'IBOutlet, vous avez une référence à EPStudentProgressQuestion au lieu de EPStudentProgressOpenQuestion ou EPStudentProgressMultipleChoiceQuestion.

Vérifiez simplement le code où vous utilisez les nouveaux IBOutlets et changez le type de variable utilisée là-bas ou ajoutez un cast à la classe appropriée.

0
Nef10 19 avril 2017 à 15:07

Votre contrôleur de vue peut avoir la mauvaise classe dans votre xib. Veuillez changer le nom de la classe UIView pas le dans le propriétaire du fichier comme l'image

enter image description here

Vous avez également appelé une méthode [d'auto-configuration] dans:

- (instancetype)initWityQuestionType:(EPStudentProgressQuestionType)questionType {
    self = [super init];
    if (self) {
        self.questiontype = questionType;
        [self setupView];
    }
    return self;
}

Vous n'avez pas besoin de le rappeler

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

Et

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

Il crée une boucle d'initialisation et provoque une fuite de mémoire.

0
Evana 19 avril 2017 à 16:06