Since xcode 4.4 you don’t need to @synthesize properties anymore (see here), the compiler does it for you. So, why does the compiler complain
use of the undeclared identifier _aVar
in my viewDidLoad method of ViewControllerSubclass:
@interface ViewController : UIViewController
@property (assign, nonatomic) int aVar;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.aVar = 5;
NSLog(@"Super value: %d", _aVar);
}
@end
@interface ViewControllerSubclass : ViewController
@end
@interface ViewControllerSubclass ()
@property (assign, nonatomic) int aVar;
@end
@implementation ViewControllerSubclass
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"Subclass value: %d", _aVar);
}
@end
If I move everything to the one file instead of 4 separate files for the respective interfaces and implementations, the compiler instead complains that _aVar is private. But _aVar should have been automatically synthesized in my ViewControllerSubclass.
Still keeping everything in 1 file, if I move the initial property declaration to a class extension:
@interface ViewController ()
@property (assign, nonatomic) int aVar;
@end
The build still fails saying that _aVar is private.
If I go back to the 4 file setup for the respective interfaces and implementations xcode builds without even a warning.
If I then run the code:
[[[ViewControllerSubclass alloc] init] view];
the log statements in the above examples print out the following:
Super value: 0
Subclass value: 5
It makes sense that NSLog(@"Super value: %d", _aVar); produced a result of 0 because this variable is supposed to be private to the superclass. But then, why does NSLog(@"Subclass value: %d", _aVar); produce a result of 5??
This is all very odd.
When you make the superclass declaration public, the compiler won’t attempt to re-synthesize the property; it assumes that’s been taken care of in the superclass. Thus,
_aVaris not in scope anywhere in the subclass. It’s private anyway, so even when you put them all in the same file that’s why you see those errors.However when you make the superclass property declaration inside the class extension, the compiler will auto-synthesize the property for both the superclass and the subclass. This ends up with both classes having private instance variables _aVar (with two distinct addresses). However, when the superclass
viewDidLoadmethod sets the property, the method invokes the subclass’s accessors, which set the value of the subclass’s private _aVar variable, and not the superclass’s. So that explains why you see the superclass value not changing.Hope this helps!