Objective-C: _variable - PullRequest
       21

Objective-C: _variable

1 голос
/ 17 декабря 2011

ОК, должно быть, об этом уже спрашивали, но я выглядела как сумасшедшая и ничего не нашла:

У меня в приложении iphone есть простой массив, который я определяю так:

@property (nonatomic, strong) NSArray *pages;
@synthesize pages = _pages;

Я видел это в образце кода Apple и думал, что это хороший путь для написания self.pages (т. Е. _Pages заменяет self.pages) примерно так:

_pages = [[NSArray alloc] init];

, но затем у Apple это снова (не совсем так, но похоже, что они постоянно меняются местами):

self.pages = [NSKeyedUnarchiver unarchiveObjectWithData:contents];

И наконец:

[_pages release];

Что меня совершенно смущает.Какая разница между _pages и self.pages?

Спасибо за вашу помощь.

Ответы [ 5 ]

5 голосов
/ 17 декабря 2011

_pages - это имя объекта ivar .pages - это другое имя свойства.
Итак, @synthesize pages = _pages;, наконец, говорит о том, что pages - это свойство для ивара _pages.

Вы получите прямой доступ к ивару через _pages в инициализаторах и методах dealloc.В любом месте имя свойства используется для получения / установки его значения.

2 голосов
/ 17 декабря 2011

Это различие обусловлено распространенными практиками присвоения имен и использования.

И переменная экземпляра, и свойство ссылаются на один и тот же объект. Разница в именовании используется для указания на разницу между ivar (_pages) и свойством (pages).

Ивару принадлежит экземпляры класса, и они сами могут обрабатывать для него операции владения (alloc, retain, release и т. Д.) Как правило, эти операции владения происходят в init и dealloc.

С другой стороны, свойство предоставляет «назначенную» точку доступа для ивара. Методы свойств (установщик и получатель) могут выполнять дополнительные операции, необходимые для правильного управления иваром. Поэтому прямой доступ к ivar (как шаблон использования) не рекомендуется, даже в пределах объектов-владельцев. Например, сеттер может быть реализован так:

- (void) setPages:(NSArray *)newValue {
    [newValue retain];

    // additional operations that you will miss if you use the ivar 
    [someObject someUsefulOperationThatIsReallyNeeded];

    [pages release];
    _pages = newValue;
}
2 голосов
/ 17 декабря 2011

Когда вы используете простое назначение:

_pages = ...

Вы просто устанавливаете переменную экземпляра.

Когда вы используете назначение свойства:

self.pages = ...

Он вызывает метод, автоматически синтезируемый компилятором (или определяемый вами), и для синтеза этого метода он проверяет тип свойства (retain, assign, ...) и пишет код, соответствующий этому типу свойства.

1 голос
/ 17 декабря 2011

_pages - переменная экземпляра, а pages - имя свойства. Доступ к свойству осуществляется через методы получения и установки pages, а setPages: object.pages эквивалентно [object pages] или для вашего примера `[self setPages: [NSKeyedUnarchiver unarchiveObjectWithData: contents]];

Таким образом, единственный действительный объект - это переменная экземпляра _pages, и только этим можно управлять памятью.

Действующий код свойства и синтезатора дают то же, что и этот код (на практике может быть дополнительный код для управления памятью и блокировки потоков

@interface MyClass
{
 ...
    NSArray *_pages 
}

- (NSArray*)pages;
- (void)setPages:(NSArray*)newValue;

@end

@implementation MyClass
- (NSArray*)pages
{
    return _pages;
}
- (void)setPages:(NSArray*)newValue
{
    _pages = newValue; // Note in non ARC code there would be some memort managment here
}

@end
0 голосов
/ 17 декабря 2011

Вы можете ссылаться на свойство @synthesized как instanceVariableName или self.propertyName.Два имени могут быть одинаковыми или разными.

Когда вы ссылаетесь как instanceVariableName и изменяете значение, никакая логика сохранения / копирования связанного свойства не применяется - вы просто ссылаетесь на«сырая» переменная.Когда вы ссылаетесь на self.propertyName, применяется логика сохранения / копирования , и, например, если свойство объявлено как «сохранить», то старое значение будет освобождено, а новоесохраняемое значение.

При назначении уже сохраненному значению (например, от alloc / init) свойству проще (если это инициализация, где свойство ранее было nil), присвоить instanceVariableName и пропустите необходимость release значения (так что чистое число retains будет 1 в конце операции).Но при присваивании свойству значения, отличного от retained (отличного от autoreleased retain), вы хотите, чтобы свойство имело значение retain, поэтому вы должны использовать нотацию self.propertyName.

Использование начального "_" для переменной экземпляра, которая также является свойством, является простым соглашением, позволяющим разделить эти два элемента и избежать случайной ссылки на одну (путем ошибочного добавления / удаления self), когда вы имели в виду другую.

...