32 votes

Remplacer le setter @property et la boucle infinie

Il y a la classe A avec :

@interface ClassA : NSObject {
}
@property (nonatomic, assign) id prop1;
@end

@implementation
@synthesize prop1;
@end

alors j'ai une sous-classe

@interface ClassB : ClassA {
}
@end

@implementation

- (id)init {
    self = [super init];
    if (self) {
    }
    return self;
}

//This is infinite loop
- (void) setProp1:(id)aProp
{
    self.prop1 = aProp;
}
@end

et c'est une boucle infinie parce que setProp1 de la classe B appelle [ClassB setProp1:val] de l'intérieur de la classe B.

J'ai déjà essayé d'appeler [super setProp1] mais ceci

Comment écraser @property et assigner une valeur dans le setter écrasé ? Et supposons que je ne puisse pas modifier ClassA.

46voto

Sherm Pendley Points 10822

Il suffit d'assigner directement à la variable d'instance, sans utiliser la syntaxe point pour appeler le setter :

- (void) setProp1:(id)aProp
{
    self->prop1 = aProp;
}

Mais ça pose la question. Tout ce que fait cet accesseur est exactement ce que le parent aurait fait - alors quel est l'intérêt de remplacer le parent ?

20voto

bollhav Points 303

Avec XCode 4.5+ et LLVM 4.1, il n'est pas nécessaire de @synthétiser, vous obtiendrez un _prop1 auquel vous pourrez vous référer.

- (void) setProp1:(id)aProp
{
    _prop1 = aProp;
}

Cela fonctionnera très bien.

6voto

Chris Livdahl Points 1342

Vous ne devez pas utiliser "self" dans le setter car cela crée un appel récursif.

Vous devez également vous assurer que vous n'affectez pas le même objet, conserver le nouvel objet et libérer l'ancien objet avant de l'affecter.

Et vous devez redéfinir le nom du setter, comme suggéré ci-dessus :

@synthesize prop1 = prop1_; 

...

- (void) setProp1:(id)aProp
{
    if (prop1_ != aProp) {
        [aProp retain]; 
        [prop1_ release]; 
        prop1_ = aProp;
    }
}

5voto

pixelfreak Points 7385

Une autre alternative est de donner un autre nom à la variable synthétisée, comme ceci :

@synthesize selectedQuestion = _selectedQuestion;

Et ensuite y faire référence en tant que _selectedQuestion . Cela évite d'écrire accidentellement selectedQuestion alors que vous vouliez dire self.selectedQuestion.

Toutefois, Apple déconseille l'utilisation de l'underscore. Vous pouvez utiliser un autre nom, mais la méthode de @Sherm est la meilleure, à mon avis.

3voto

Daniel Points 14150

Tout simplement @synthesize la propriété souhaitée dans votre sous-classe, vous pouvez alors l'utiliser comme nom pour accéder directement à la propriété :

Interface de la classe principale :

@interface AClass : NSObject

@property (nonatomic, assign) id<someProtocol> delegate;

@end

Interface de sous-classe :

@interface BCLass : AClass
@end

Mise en œuvre de la sous-classe :

@implementation BCLass

@synthesize delegate = _delegate;

- (void)setDelegate:(id<someProtocol>)d{
    _delegate = d;
}

@end

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X