Цель C: Почему мы объявляем ivars в области .h, если @property, похоже, делает это автоматически?

При реализации интерфейса кажется, что общий метод в учебниках и литературе состоит в том, чтобы объявить ivar, а затем установить @property, затем @synthesize.

@interface MyClass : NSObject {
NSString *myString;
}

@property (nonatomic, retain) NSString *myString;
@end

Тем не менее, опускание явного объявления и просто включение @property имеют тот же эффект.

@interface MyClass: NSObject {
}

@property (nonatomic, retain) NSString *myString;
@end

Итак, почему большинство людей используют @property и явное объявление? Неплохо ли это?

Ответы

Ответ 1

Это было необходимо. Существуют две версии версии Objective-C: 32-разрядная "устаревшая" среда исполнения (старая) и 32/64-разрядная среда выполнения (новая 32-разрядная среда выполнения используется только на устройствах iOS и для iOS-симулятор).

Я думаю, что единственное место, которое все еще необходимо, - это когда вы запускаете приложение в 32-битном режиме (10.5 или 10.6). В другом месте (64-битный Leopard, 64-бит Snow Leopard, Lion, iOS) использует более новую среду исполнения, которая имеет "автоматический синтез ivar", а полученные ivars называются "синтезированными иварами".

Ответ 2

Некоторые платформы поддерживают синтезированные переменные экземпляра, некоторые - нет. Явное объявление переменных экземпляра делает ваш код действительным в большем количестве мест, и до недавнего времени он был абсолютно необходим, поэтому люди все еще это делают. Через несколько лет они, вероятно, больше не будут.

Ответ 3

Используя современные версии Xcode (что-то около 4.2 или новее), нет никаких оснований объявлять iVar в заголовке EVER. Любое общедоступное должно быть объявлено как собственность.

Многие забывают, что объекты Objective C на самом деле являются указателями на C-структуры. Таким образом, любой iVar, объявленный в вашем заголовке, может быть доступен напрямую, передавая ваши геттеры и сеттеры, используя myObject->myPublicIVar. Особенно в коде, отличном от ARC, это чрезвычайно опасно. Директива @private запрещает использование оператора -> для доступа к iVars, но все же загромождает файл заголовка. Нет смысла в @private, когда есть лучшие способы.

Любое частное должно быть объявлено в вашем файле .m. Часто для этого требуется расширение класса, например:

// The .h file
@interface Foo : NSObject
@property (nonatomic, strong) NSString *myPublicString;
@end


// The .m file
@interface Foo ()
@property (nonatomic, strong) NSString *myPrivateString;
@end

@implementation Foo {
    NSString *myPrivateIVar;
}

// Xcode 4.5 or later will not require these @synthesize
@synthesize myPublicString = _myPublicString;
@synthesize myPrivateString = _myPrivateString;

@end

Подобная реализация обеспечивает публичное свойство, поддерживаемое iVar, частной собственностью, поддерживаемой iVar, и частной независимой iVar. Я включил директивы @synthesize, но они не нужны с использованием современных инструментов.

Ответ 4

@property реализует только методы доступа, сама переменная экземпляра должна существовать. Попробуйте игнорировать ivars, и он не будет работать во время выполнения, если не во время компиляции.