3

I have the following class and subclass:

@interface NSHigh : NSObject
@property (nonatomic, strong) NSArray *array;
@end
@implementation NSHigh
-(NSArray*)array
{
    _array = [[NSArray alloc] init];
    return _array;
}
@end

@interface NSLow : NSHigh
@end
@implementation NSLow
/* synthesizing makes the assertion FAIL. NO synthesizing makes the assertion PASS */
@synthesize array;
@end

Then I run this code somewhere:

NSLow *low = [[NSLow alloc] init];
assert(low.array);

So, apparently, if in the subclass NSLow I synthesize the array property, then the getter from the super class does not get called, and the assertion fails.

If I do not synthesize, then the superclass getter is called, and the assertion passes.

  1. Why does this happen?
  2. How would I access the array instance variable in the NSLow subclass without calling self.array every time?
Snowman
  • 31,411
  • 46
  • 180
  • 303

1 Answers1

8

@synthesize in NSLow will create the following getter:

- (NSArray *)array {
    return _array;
}

So, your array is never initialized and nil is returned.

You generally shouldn't use @synthesize for @properties that are declared in a superclass.

Also, you shouldn't implement a getter like the one in NSHigh. If you want to init that array lazily you should do it like this:

- (NSArray *)array {
    if (!_array) {
        _array = [[NSArray alloc] init];
    }
    return _array;
}

Finally, you shouldn't use NS prefix.

EDIT:

If you want direct access to your ivar in the subclass, you can explicitly declare it in the header like this:

@interface NSHigh : NSObject {
    NSArray *_array;
}
@property (nonatomic, strong) NSArray *array;
@end

This will allow you to access the ivar in your subclasses too.

DrummerB
  • 39,814
  • 12
  • 105
  • 142
  • So I would have to explicitly call self.property from all subclasses? There's no other way around this? What's the reasoninng for this? – Snowman Oct 03 '12 at 00:03
  • But if you really want direct access, you can explicitly declare your ivar in the superclasses interface. – DrummerB Oct 03 '12 at 00:08
  • @DrummerB Will a synthesized getter use the `_array` ivar? That is, with an underscore prefix? – millimoose Oct 03 '12 at 00:14
  • 1
    Actually no, you're right. If you simply call `@synthesize array;` if will use an ivar called `array`. If you let it synthesize automatically it will use `_array`. Or you can also use `@synthesize array = _array;` to make it use `_array` when explicitly synthesizing. – DrummerB Oct 03 '12 at 00:22
  • 1
    Shouldn't that `if (_array) ...` be `if (!_array) ...`? – Rob Oct 03 '12 at 01:48