38

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.

jephers
  • 157
  • 1
  • 6
Marcin
  • 3,694
  • 5
  • 32
  • 52

5 Answers5

58

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?

jephers
  • 157
  • 1
  • 6
Sherm Pendley
  • 13,556
  • 3
  • 45
  • 57
  • 3
    example is just for example purpose. – Marcin Jun 19 '11 at 22:29
  • 2
    No need for the `self->` part unless using GCC 4.2. – bbum Jun 20 '11 at 00:09
  • 3
    True, 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. – Sherm Pendley Jun 20 '11 at 00:20
  • This didn't work out for me, please check out my solution: http://stackoverflow.com/a/12465444/662605 – Daniel Sep 17 '12 at 18:54
  • @Daniel You have exactly what he has. – RileyE Dec 28 '12 at 20:08
  • @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. ;) – josephrider Jul 28 '16 at 03:37
24

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.

bollhav
  • 543
  • 6
  • 11
9

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;
    }
}
Chris Livdahl
  • 4,662
  • 2
  • 38
  • 33
  • you should only do this for a `retain` property, the OP's example is an `assign` property. – pancake Jun 30 '14 at 23:00
  • The 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. – LargeGlasses Oct 27 '15 at 00:12
5

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.

pixelfreak
  • 17,714
  • 12
  • 90
  • 109
4

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
Daniel
  • 23,129
  • 12
  • 109
  • 154