Требуют ли объявленные свойства соответствующей переменной экземпляра? - PullRequest
102 голосов
/ 19 июня 2010

Требуются ли свойства в Objective-C 2.0 для объявления соответствующей переменной экземпляра? Например, я привык делать что-то вроде этого:

myobject.h

@interface MyObject : NSObject {
NSString *name;
}
@property (nonatomic, retain) NSString *name;
@end

MyObject.m

@implementation
@synthesize name;
@end

Однако, что если бы я сделал это вместо:

myobject.h

@interface MyObject : NSObject {
}
@property (nonatomic, retain) NSString *name;
@end

Это все еще в силе? И отличается ли это от моего предыдущего примера?

Ответы [ 6 ]

94 голосов
/ 19 июня 2010

Если вы используете Modern Objective-C Runtime (это iOS 3.x или выше, или 64-битный Snow Leopard или выше), тогда вам не нужно определить ivars для ваших свойств втакие случаи.

Когда вы @synthesize свойство, ивар будет фактически синтезироваться и для вас.Это обходит сценарий «хрупкий ивар».Вы можете прочитать больше об этом на Какао с Любовью

71 голосов
/ 02 февраля 2011

В вашем интерфейсе вы можете формально объявить переменную экземпляра между фигурными скобками или через @property вне фигурных скобок, или и то, и другое.В любом случае, они становятся атрибутами класса.Разница в том, что если вы объявляете @property, то вы можете реализовать, используя @synthesize, который автоматически кодирует ваш метод получения / установки для вас.Автоустановщик кодировщика инициализирует целые числа и, например, обнуляется.Если вы объявляете переменную экземпляра и НЕ указываете соответствующий @property, то вы не можете использовать @synthesize, а должен написать свой собственный метод получения / установки.

Вы всегда можете переопределить автоматически закодированный метод получения / установки, указав свой собственный.Обычно это делается с помощью свойства managedObjectContext, которое загружается лениво.Таким образом, вы объявляете свой managedObjectContext как свойство, но затем также пишете метод -(NSManagedObjectContext *)managedObjectContext.Напомним, что метод, имя которого совпадает с именем переменной / свойства экземпляра, является методом «getter».

Метод объявления @property также позволяет использовать другие параметры, такие как retain и readonly, чего нет у метода объявления переменных экземпляра.По сути, ivar - это старый способ, а @property расширяет его и делает его более привлекательным / простым.Вы можете обратиться к любому, используя сам.Префикс или нет, это не имеет значения, если имя уникально для этого класса.В противном случае, если у вашего суперкласса есть то же имя свойства, что и у вас, вы должны указать либо как self.name, либо super.name, чтобы указать, о каком имени вы говорите.

Таким образом, вы увидите, что все меньше и меньше людей объявляют ivar s между фигурными скобками и вместо этого переходят к простому указанию @property, а затем делают @synthesize.Вы не можете сделать @synthesize в своей реализации без соответствующего @property.Синтезатор знает только, какой это тип атрибута из спецификации @property.Оператор synthesize также позволяет вам переименовывать свойства, чтобы вы могли ссылаться на свойство по одному имени (сокращенно) внутри вашего кода, но снаружи в файле .h используйте полное имя.Тем не менее, с действительно классным автозаполнением, которое теперь есть у XCode, это меньшее преимущество, но оно все еще есть.

Надеюсь, это поможет прояснить всю путаницу и дезинформацию, которые распространяются вокруг.

8 голосов
/ 13 апреля 2011

это работает в обе стороны, но если вы не объявите их в фигурных скобках, вы не увидите их значения в отладчике в xcode.

3 голосов
/ 18 марта 2013

Если вы используете XCode 4.4 или новее, он сгенерирует для вас код синтеза переменных экземпляра.

Вы просто должны объявить свойства, как показано ниже; он сгенерирует для вас синтезирующий код и переменную экземпляра, объявляющую код.

@property (nonatomic, strong) NSString *name;

будет генерировать синтезирующий код как

@synthesize name = _name;

и вы можете получить доступ к переменной экземпляра, используя _name похоже объявить

NSString* _name

но если вы объявите свойство только для чтения, оно будет выглядеть как

@property (nonatomic, strong, readonly) NSString *name;

сгенерирует код

@synthesize name;

или

@synthesize name = name; 

Таким образом, вы должны получить доступ к мгновенному имени переменной без префикса "_" В любом случае, вы можете написать свой собственный синтезирующий код, тогда компилятор сгенерирует код для вас. Вы можете написать

@synthesize name = _name;
3 голосов
/ 28 марта 2011

Из документации:

В целом поведение свойств идентично как в современных, так и в устаревших средах выполнения (см. «Версии и платформы среды выполнения» в Руководстве по программированию среды выполнения Objective-C). Есть одно ключевое отличие: современная среда выполнения поддерживает синтез переменных экземпляра, тогда как устаревшая среда выполнения этого не делает.

Чтобы @synthesize работал в устаревшей среде выполнения, необходимо либо предоставить переменную экземпляра с тем же именем и совместимым типом свойства, либо указать другую существующую переменную экземпляра в операторе @synthesize. В современной среде выполнения, если вы не предоставите переменную экземпляра, компилятор добавит ее для вас.

1 голос
/ 11 января 2012

Язык программирования Objective-C: Директивы реализации свойств

Существуют различия в поведении синтеза средства доступа, которые зависят от времени выполнения (см. Также «Разница во времени выполнения»):

  • Для устаревших сред выполнения переменные экземпляра уже должны быть объявлены в блоке @interface текущего класса.Если переменная экземпляра с тем же именем, что и у свойства, существует, и если ее тип совместим с типом свойства, она используется - в противном случае вы получите ошибку компилятора.

  • Длясовременные среды выполнения (см. «Версии и платформы среды выполнения» в Руководстве по программированию среды выполнения Objective C), переменные экземпляра синтезируются по мере необходимости.Если переменная экземпляра с таким именем уже существует, она используется.

...