web-dev-qa-db-fra.com

Synthèse automatique des propriétés (@property) et héritage

Avec XCode 5.1, un nouvel avertissement apparaît. Cela m'a fait comprendre - évidemment - que je faisais quelque chose de mal.

L'idée était d'avoir un objet (un modèle) et sa version mutable qui hérite de la classe d'origine. L'idée est donc d'ouvrir une propriété qui était readonly à readwrite

@interface Car : NSObject
    @property (strong, readonly) NSString *name;
@end

@interface MutableCar : Car
    @property (strong, readwrite) NSString *name;
@end

Ceux-ci doivent être dans des fichiers séparés (comme deux classes normales).

Et il donne cet avertissement:

Auto property synthesis will not synthesize property 'name' because it is 'readwrite' but it will be synthesized 'readonly' via another property

Je voudrais donc savoir quelle est la bonne solution pour faire quelque chose comme ça, si c'est même possible. s'il est nécessaire d'écrire des accesseurs et d'éviter d'utiliser la synthèse automatique, etc. Veuillez être précis et appuyer votre réponse avec de la documentation ou autre.

42
AncAinu

Je suggère de synthétiser explicitement la propriété sur votre implémentation MutableCar. Un péché:

@implementation MutableCar

@synthesize name;

@end

De cette façon, clang n'essaiera pas d'utiliser autosynthèse

Modifier:

Si vous ne voulez pas utiliser l'encapsulation et pour une autre raison, vous devez accéder à l'ivar à partir de la classe parente, alors vous devez faire un peu plus d'efforts:

Tout d'abord, le fichier Car .h reste le même (j'ai ajouté une méthode printVar pour imprimer l'ivar et la propriété):

@interface Car : NSObject

- (void)printVar;

@property (strong, readonly) NSString *name;

@end

Maintenant, sur le fichier .m, j'implémente la méthode printVar et j'ajoute également une extension de classe pour dire à clang de créer le setter:

// Private class extension, causes setName: to be created but not exposed.
@interface Car ()

@property (strong, readwrite) NSString *name;

@end

@implementation Car

- (void)printVar
{
    NSLog(@"<Car> Hello %@, ivar: %@", self.name, _name);
}

@end

Vous pouvez maintenant créer votre MutableCar.h comme auparavant:

@interface MutableCar : Car

@property (strong, readwrite) NSString *name;

@end

et votre MutableCar.m devrait ressembler à ceci:

@implementation MutableCar

@dynamic name;

- (void)printVar
{
    [super printVar];
    NSLog(@"<MutableCar> Hello %@", self.name);
}

@end

De cette façon, l'ivar _name sur le parent est réellement écrit en utilisant le setter parent et vous pouvez y accéder.

59
fz.