Если подкласс ссылается на суперкласс ivar, синтезируя несвязанное свойство fails

Редактировать: Я только что заметил этот другой вопрос о переполнении стека, который задает примерно то же самое: Почему подкласс @property без соответствующего ivar скрывает ivars суперкласса?

Это интересное поведение, которое я не могу найти документированным ни в чем официальном или неофициальном (блог, твит, вопрос SO и т. Д.). Я свел его к сути и проверил в новом проекте Xcode, но я не могу его объяснить.

MyBaseClass имеет переменную экземпляра:

@interface MyBaseClass : NSObject {
    NSObject *fooInstanceVar;
}
@end

MySubclass расширяет MyBaseClass и объявляет совершенно несвязанное свойство (то есть , свойство не предназначено для поддержки переменной экземпляра):

#import "MyBaseClass.h"
@interface MySubclass : MyBaseClass { }
@property (nonatomic, retain) NSObject *barProperty;
@end

Если реализация MySubclass не синтезирует свойство, но реализует методы доступа, все в порядке (без ошибок компилятора):

#import "MySubclass.h"
@implementation MySubclass

- (NSObject*)barProperty {
    return [[NSObject alloc] init]; // pls ignore flagrant violation of memory rules.
}

- (void)setBarProperty:(NSObject *)obj { /* no-op */ }

- (void)doSomethingWithProperty {
    NSArray *array = [NSArray arrayWithObjects:self.barProperty, fooInstanceVar, nil];
    NSLog(@"%@", array);
}
@end

Но если я удалю методы доступа к свойству и заменю их объявлением synthesize для свойства, я получу ошибку компилятора: 'fooInstanceVar' undeclared (первое использование в этой функции) .

#import "MySubclass.h"
@implementation MySubclass
@synthesize barProperty;

- (void)doSomethingWithProperty {
    NSArray *array = [NSArray arrayWithObjects:self.barProperty, fooInstanceVar, nil];
    NSLog(@"%@", array);
}
@end

Эта ошибка исчезнет, ​​если я удалю либо объявление synthesize , либо если я не буду ссылаться на переменную экземпляра fooInstanceVar из MySubclass.m, либо если я поставлю все определения интерфейса и реализации в одном файле. Эта ошибка также возникает в настройках сборки GCC 4.2 и GCC / LLVM.

Кто-нибудь может объяснить, что здесь происходит?

18
задан Community 23 May 2017 в 12:01
поделиться