В чем разница между ivars и свойствами в Objective-C
в чем семантическая разница между этими 3 способами использования ivars и свойств в objective-c?
1.
@class MyOtherObject;
@interface MyObject {
}
@property (nonatomic, retain) MyOtherObject *otherObj;
2.
#import "MyOtherObject.h"
@interface MyObject {
MyOtherObject *otherObj;
}
@property (nonatomic, retain) MyOtherObject *otherObj;
3.
#import "MyOtherObject.h"
@interface MyObject {
MyOtherObject *otherObj;
}
2 ответов
номер 1 отличается от двух других путем прямого объявления класса MyOtherObject, чтобы минимизировать количество кода, видимого компилятором и компоновщиком, а также потенциально избежать круговых ссылок. Если вы сделаете это таким образом, не забудьте поместить #import в .m-файл.
объявив свойство@, (и сопоставляя @synthesize в .m) файл, Вы автоматически генерируете методы доступа с семантикой памяти, обрабатываемой, как вы указываете. Эмпирическое правило для большинства объектов Сохранить, но NSStrings, например, должны использовать Copy. В то время как Синглеты и делегаты обычно должны использовать Assign. Рукописные аксессоры утомительны и подвержены ошибкам, поэтому это экономит много ввода и немых ошибок.
кроме того, объявление синтезированного свойства позволяет вызвать метод доступа с помощью точечной нотации, как это:
self.otherObj = someOtherNewObject; // set it
MyOtherObject *thingee = self.otherObj; // get it
вместо обычного пути передачи сообщений:
[self setOtherObject:someOtherNewObject]; // set it
MyOtherObject *thingee = [self otherObj]; // get it
за кулисами вы действительно вызываете метод, который выглядит как это:
- (void) setOtherObj:(MyOtherObject *)anOtherObject {
if (otherObject == anOtherObject) {
return;
}
MyOtherObject *oldOtherObject = otherObject; // keep a reference to the old value for a second
otherObject = [anOtherObject retain]; // put the new value in
[oldOtherObject release]; // let go of the old object
} // set it
...или
- (MyOtherObject *) otherObject {
return otherObject;
} // get it
полная боль в заднице, правильно. Теперь сделайте это для каждый Ивар в классе. Если вы не сделаете это правильно, вы получите утечку памяти. Лучше всего просто позволить компилятору делать работу.
Я вижу номер 1 нет Ивар. Предполагая, что это не опечатка, это нормально, потому что директивы @property / @synthesize объявят ivar для вас также, за кулисами. Я верю это новое для Mac OS X-Snow Leopard и iOS4.
число 3 не имеет этих аксессоров, поэтому вы должны написать их сами. Если вы хотите, чтобы ваши методы доступа имели побочные эффекты, вы выполняете стандартный танец управления памятью, как показано выше, а затем выполняете любую побочную работу внутри метода доступа. Если вы синтезируете свойство а также написать свой собственный, потом код версия приоритет.
Я все?
в старые времена у вас были ivars, и если вы хотели, чтобы какой-то другой класс установил или прочитал их, вам нужно было определить геттер (т. е. -(NSString *)foo)
и сеттер (т. е. -(void)setFoo:(NSString *)aFoo;
).
какие свойства дают вам сеттер и геттер бесплатно (почти! вместе с Иваром. Поэтому, когда вы определяете свойство сейчас, вы можете установить атомарность (например, вы хотите разрешить несколько действий настройки из нескольких потоков), а также назначить/сохранить / скопировать семантику (т. е. сеттер копирует новое значение или просто сохраняет текущее значение - важно, если другой класс пытается установить свойство string с изменяемой строкой, которая может быть изменена позже).
это @synthesize
делает. Многие люди оставляют имя ivar одинаковым, но вы можете изменить его, когда пишете свой оператор synthesize (т. е. @synthesize foo=_foo;
означает сделать Ивар по имени _foo
свойства foo
, поэтому, если вы хотите прочитать или написать это свойство, и вы не используете self.foo
, вы должны использовать _foo = ...
- это просто поможет вам поймать прямые ссылки на Ивар, если вы хотите только пройти через сеттер и геттер).
начиная с Xcode 4.6, вам не нужно использовать @synthesize
оператор-компилятор сделает это автоматически и по умолчанию добавит имя ivar с _
.