Marcin
Marcin

Reputation: 3784

Override @property setter and infinite loop

There is Class A with:

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

@implementation
@synthesize prop1;
@end

then I have subclass

@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

and this is infinite loop because setProp1 from ClassB calls [ClassB setProp1:val] from within ClassB.

I've already tried call [super setProp1] but this

How to overwrite @property and assign value inside overwritten setter ? And let's assume I can't modify ClassA.

Upvotes: 38

Views: 29164

Answers (5)

bollhav
bollhav

Reputation: 543

With XCode 4.5+ and LLVM 4.1 there is no need to @synthesize, you will get a _prop1 to refer to.

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

Will work just fine.

Upvotes: 24

Daniel
Daniel

Reputation: 23359

Simply @synthesize the desired property in your subclass, then you can use that as the name to access the property directly:

Main Class interface:

@interface AClass : NSObject

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

@end

Subclass interface:

@interface BCLass : AClass
@end

Subclass implementation:

@implementation BCLass

@synthesize delegate = _delegate;

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

@end

Upvotes: 4

Chris Livdahl
Chris Livdahl

Reputation: 4740

You shouldn't use "self" inside the setter since that creates the recursive call.

Also, you should check to make sure you're not assigning the same object, retain the new object and release the old object before assignment.

And you should redefine the setter name, as suggested above:

@synthesize prop1 = prop1_; 

...

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

Upvotes: 9

Sherm Pendley
Sherm Pendley

Reputation: 13612

Just assign to the instance variable directly, without using dot syntax to call the setter:

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

That kind of begs the question though. All this accessor does is exactly what the parent would have done - so what's the point of overriding the parent at all?

Upvotes: 58

pixelfreak
pixelfreak

Reputation: 17834

Another alternative is to set the synthesized variable to another name like so:

@synthesize selectedQuestion = _selectedQuestion;

And then refer to it as _selectedQuestion. This prevents accidentally writing selectedQuestion when you meant self.selectedQuestion.

However, Apple recommend against using underscore. You can use another name, but @Sherm's method is the best, imho.

Upvotes: 5

Related Questions