BuySellAds.com

Until Dec 3rd, 44% off all Manning books, including Barcodes with iOS! Promo code: mobicftw
Our DNA is written in Objective-C
Jump

Implicit IVAR Synthesis

Apple recently added the ability for Xcode to automatically create instance variables for you. This means you no longer need to add an @synthesize for each property you create.

But does it really do that always, or are there scenarios where no _ivar is needed? Are there situations wehre you do need an explicit synthesis? For example what about properties which are just passing through values to a sub-object?

I wanted to know, so I experimented a bit. I even filed a Radar with Apple for clarification which came back with a good explanation.

Let’s create a new class for our test.

@interface TestObject : NSObject
 
@property (nonatomic, copy) NSString *string;
 
@end

Having not added any @synthesize will still get an instance variable _string be generated for us. To prove this, we add a method that accesses it:

#import "TestObject.h"
 
@implementation TestObject
 
- (NSString *)description
{
   return _string;
}
 
@end

No compiler error so far, so _string indeed exists.

Let’s override the setter.

- (void)setString:(NSString *)string
{
   // don't accept nil
   NSParameterAssert(string);
 
  _string = [string copy];
}

The synthesize is inferred, Xcode simply assumes that we had written the following somewhere in the implementation (personally I prefer to have these at the bottom).

@synthesize string = _string

Note that if you specify the synthesize like in the olden days the compiler no longer accepts the _string:

@synthesize string;

This creates an instance variable that is also called string, which is inconvenient since that forced people to name they setter method parameters something like aString. Yuck!

Now let’s also overwrite the getter:

- (NSString *)string
{
	return _string;
}

And now something curious happens. This was the reason why I filed a Radar:

missing ivar

Like  anybody who never really gave much thought to this implicit mechanism I got confused by the sudden appearance of these build errors. Apple’s response to my inquiry explains it nicely:

Engineering has determined that this issue behaves as intended based on the following information:

This is correct behavior. Once both the getter and setter are provided no implicit storage gets created. When you need an ivar, you will need to use @synthesize.

If you have a readwrite property then you don’t get an implicit ivar if you overwrite both setter and getter. Does it make a difference if the property is change to readonly? Yes. For readonly properties you only have to override the getter method to prevent ivar synthesis.

Conclusion

Since I was used to supporting older Xcode versions with my open source frameworks like DTCoreText I still had the habit of explicitly defining all instance variables as well as adding an @synthesize property = _ivar line for each of them. This is why I didn’t benefit from or understand implicit IVAR generation until now. Honest mistake.

But working on apps that require more recent Xcode versions to build allows me to also save me some typing because I now know how implicit IVAR synthesis works. To summarize: For readwrite properties you get an _ivar if you don’t overwrite both the setter and getter. For readonly properties you only get an _ivar if you don’t overwrite the getter.


Categories: Q&A

%d bloggers like this: