Свойства Objective-C, как они работают? - PullRequest
2 голосов
/ 10 февраля 2011


Предположим, у нас есть класс Foo со свойством bar.
Объявлено так в шапке:

@interface Foo : NSObject {
    int bar;
}

@property (nonatomic, assign) int bar;

@end

В .m у меня есть @synthesize bar; конечно.

Теперь мой вопрос : если я удаляю строку int bar;, свойство ведет себя так же, поэтому действительно ли эта строка необходима? Я скучаю по какой-то фундаментальной концепции?

Спасибо!

Ответы [ 5 ]

3 голосов
/ 10 февраля 2011

"Современная" среда выполнения Objective C автоматически генерирует ивары, если они еще не существуют, когда встречаются @synthesize.

Преимущества их пропуска:

  • Меньше дублирования в вашем коде. И @property дает тип, имя и использование (свойство!) Ивара, так что вы ничего не теряете.
  • Даже без явного объявления ивара, вы все равно можете получить доступ к ивару напрямую. (В одном старом выпуске Xcode есть ошибка, которая предотвращает это, но вы не будете использовать эту версию.)

Есть несколько предостережений:

  • Это не поддерживается со "старой" средой выполнения на 32-битной Mac OS X. ( поддерживается в последних версиях симулятора iOS.)
  • Xcode может не отображать автоматически сгенерированные ivars в отладчике. (Я считаю, что это ошибка.)

Из-за проблемы с отладчиком в настоящий момент я явно добавляю все свои ивары и помечаю их так:

@interface Foo : NSObject {
    #ifndef SYNTHESIZED_IVARS
    int ivar;
    #endif
}

@property (nonatomic, assign) int bar;

@end

Мой план состоит в том, чтобы удалить этот блок, когда я подтвердил, что отладчик может показать ивары. (Насколько я знаю, это уже произошло.)

3 голосов
/ 10 февраля 2011

Если не существует переменной экземпляра (ivar) с тем же именем, что и у свойства, современная среда выполнения создает новый ivar с указанным именем свойства для хранения значения свойства, когда оно видит @ synthesize.

Есливаше свойство не было определено как неатомичное, и вы хотите, чтобы ваш код был потокобезопасным, это может помочь вам не ссылаться на ivar (независимо от того, объявили вы его или он был синтезирован), так как это помешает вам получить прямой доступ к нему при изменении свойства.Насколько мне известно, нет способа получить такую ​​же блокировку, которую получает @synthesize для атомарного свойства, и, следовательно, вы не можете выполнять безопасное чтение ивара атомарного свойства, кроме как с помощью его синтезированного метода доступа (если вы не закодировали явный установщик и не заблокировали что-тосам). Если вы заинтересованы в написании своих собственных аксессоров, у меня есть сообщение на эту тему здесь.

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

Редактировать: Я исправил параграф 1, сказав, что синтезированный ивар имеет имяимущество;Я не видел обсуждения его названия в документах Apple, поэтому предположил, что он недоступен для пользователей.Спасибо комментаторам за указание на это.

2 голосов
/ 10 февраля 2011

В последней среде выполнения Objective C оказалось, что все ivars (в данном случае bar) динамически добавляются в класс из объявления @ property / @ synthesize и не нуждаются в соответствующем объявлении ivar в заголовке класса.,Единственное предостережение: последняя среда выполнения Objective C, поддерживающая эту функцию, не включает поддержку 32-битных приложений.

Эта страница из превосходного Какао с любовью блога объясняет больше.

1 голос
/ 10 февраля 2011

Если вы используете современную среду выполнения Obj-C (например, с компилятором LLVM в Xcode 4), компилятор может автоматически создать переменную экземпляра для вас. В этом случае вам не нужно объявлять ivar.

Современная среда выполнения поддерживается iOS, iOS Simulator и 64-разрядной Mac OS X. Вы не можете создать свой проект для 32-разрядной OS X с современной средой выполнения.

0 голосов
/ 10 февраля 2011

Я считаю, что это работает только в 64-битном режиме. Если вы попытаетесь построить для 32-битной цели, она выдаст исключение.

Скотт Стивенсон имеет хороший обзор изменений в target-c 2 и упоминает 64-битные изменения времени выполнения здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...