Question

So the auto synthesize of properties is awesome. However, when you provide both a getter and a setter, you get an error.

@property (strong, nonatomic) NSArray *testArray;

- (NSArray *)testArray {
    return _testArray;
}

- (void)setTestArray:(NSArray *)testArray {
    _testArray = testArray;
}

Error: Use of undeclared identifier '_testArray'.

Adding @synthesize testArray = _testArray; solves the problem. I am just wondering why this is?

Was it helpful?

Solution

When you provide both getter and setter, there is often just no need for an instance variable at all, i.e. when you just forward those messages or store data in other places.

As soon as one of them is missing, the ivar is needed to synthesize that functionality.

If I remember correctly, for readonly properties the analogue assumption holds as well.

OTHER TIPS

Under the most recent compiler/runtime, when you use

@synthesize testArray = _testArray;

the compiler creates

  • a _testArray ivar, if it doesn't already exists;
  • a testArray method, if you haven't implemented it;
  • a setTestArray: method, if you haven't implemented it.

If you use

@synthesize testArray;

the compiler creates a testArray ivar if it doesn't already exists, instead of _testArray.

If you don't use @synthesize, and rely on the autosynthesis, the _testArray ivar is created only if (both have to apply)

  • _testArray doesn't already exist;
  • at least one method has been synthesized (getter for readonly, getter and/or setter for readwrite).

In your example, you have implemented all methods, so the autosynthesis doesn't synthesize any, so it doesn't create the ivar. You can either declare the _testArray ivar yourself, or use an explicit synthesis as you did.

I did some testing:

Under recent Objective-c convention, you do not need to synthesize properties.

If you do

@property (strong, nonatomic) Business* theBiz;

iOs will automatically create a private ivar variable called _theBiz;

If you only implement a getter or a setter it seems to work just fine:

-(void)setTheBiz:(Business *)theBiz
{
    _theBiz = theBiz;
}

However, if you declare BOTH, even if one of them are just empty function you'll get compile error.

-(void)setTheBiz:(Business *)theBiz
{
    _theBiz = theBiz;
}

-(Business *) theBiz
{

}

When you implement BOTH getter and setter you will get a compile error saying that therre is no such thing as _theBiz.

That can be easily fixed by adding:

@synthesize theBiz = _theBiz;

But that defeat the whole point of this awesome new feature of Objective-c.

I wonder if this is by design or I am just missing something. What does apple thing?

My best guess is it's a bug.

Guillaume's answer doesn't address that fact.

He said that

at least one method has been synthesized

It seems that _theBiz would have been created if only ONE of getter or setter is set. When both are set it's no longer created and that must be a bug. In fact, none have to be set at all and the ivar will still be created.

The only way to fix that is to explicitly do

@synthesize theBiz = _theBiz;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top