Override @property setter and infinite loop
Solution 1
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?
Solution 2
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.
Solution 3
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;
}
}
Solution 4
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.
Solution 5
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
Marcin
Passionate developer. iOS. https://github.com/krzyzanowskim
Updated on March 15, 2020Comments
-
Marcin over 4 years
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.
-
Marcin about 13 yearsexample is just for example purpose.
-
bbum about 13 yearsNo need for the
self->
part unless using GCC 4.2. -
Sherm Pendley about 13 yearsTrue, but AFAIK it does no harm, and it serves as a visual reminder that I'm doing something a bit out of the ordinary, accessing an ivar without going through its accessor method.
-
Daniel almost 12 yearsThis didn't work out for me, please check out my solution: stackoverflow.com/a/12465444/662605
-
RileyE over 11 years@Daniel You have exactly what he has.
-
pancake almost 10 yearsyou should only do this for a
retain
property, the OP's example is anassign
property. -
LargeGlasses over 8 yearsThe part that saved me was You shouldn't use "self" inside the setter since that creates the recursive call. Once I replaced self. with an underscore, the magic took place.
-
josephrider almost 8 years@ShermPendley Personally, I don't need a visual reminder when I'm IN the accessor block. It's like adding a sign for TOILET over the toilet. EDIT: unless of course alcohol is involved, then both may be necessary. ;)