Почему переименовать синтезированные свойства в iOS с ведущими подчеркиваниями?

Возможный дубликат:
Как подчеркивается символ подчеркивания перед переменной в classе цели-c cocoa?

При создании нового проекта в Xcode 4 код шаблона добавляет символ подчеркивания, когда он синтезирует ivars в файле реализации как:

@synthesize window = _window; 

или:

 @synthesize managedObjectContext = __managedObjectContext; 

Может ли кто-нибудь сказать мне, что здесь делается? Я не полный ник, но это один из аспектов объективности – я не понимаю.

Еще одна путаница; в реализации делегата приложения, после синтеза windows iVar, как указано выше, в приложении didFinishLaunchingWithOptions: метод windows и viewController ivars относятся к использованию self:

 self.window.rootViewController = self.viewController [self.window makeKeyAndVisible]; 

но в методе dealloc это _window или _viewController

благодаря

4 Solutions collect form web for “Почему переименовать синтезированные свойства в iOS с ведущими подчеркиваниями?”

Это артефакт предыдущей версии среды выполнения Objective-C.

Первоначально @synthesize использовался для создания методов доступа, но среда выполнения все же требовала, чтобы переменные экземпляра были явно заданы:

 @interface Foo : Bar { Baz *_qux; } @property (retain) Baz *qux; @end @implementation Foo @synthesize qux = _qux; - (void)dealloc { [_qux release]; [super dealloc]; } @end 

Люди будут префикс своих переменных экземпляра, чтобы отличать их от своих свойств (хотя Apple не хочет, чтобы вы использовали символы подчеркивания, но это другое дело). Вы синтезируете свойство, чтобы указать на переменную экземпляра. Но дело в том, что _qux – это переменная экземпляра, а self.qux (или [self qux] ) – это сообщение qux отправленное объекту self .

Мы используем переменную экземпляра непосредственно в -dealloc ; используя метод доступа, будет выглядеть так (хотя я не рекомендую его по причинам, которые я объясню вкратце):

 - (void)dealloc { self.qux = nil; // [self setQux:nil]; [super dealloc]; } 

Это приводит к высвобождению qux , а также к обнулению ссылки. Но у этого могут быть неудачные побочные эффекты:

  • Вы можете запустить некоторые неожиданные уведомления. Другие объекты могут наблюдать изменения в qux , которые записываются, когда используется метод доступа для его изменения.
  • (Не все согласны в этом вопросе 🙂 Нулевая указатель, поскольку он может скрыть логические ошибки в вашей программе. Если вы когда-либо обращались к переменной экземпляра объекта после того, как объект был освобожден, вы делаете что-то серьезно неправильно. Однако из-за семантики nil messaging Objective-C вы никогда не узнаете, использовав аксессуар для установки на nil . Если бы вы выпустили переменную экземпляра напрямую и не обнулили ссылку, доступ к удаленному объекту вызвал бы громкий EXC_BAD_ACCESS .

Более поздние версии среды выполнения добавили возможность синтезировать переменные экземпляра в дополнение к методам доступа. В этих версиях среды выполнения приведенный выше код может быть опущен переменными экземпляра:

 @interface Foo : Bar @property (retain) Baz *qux; @end @implementation Foo @synthesize qux = _qux; - (void)dealloc { [_qux release]; [super dealloc]; } @end 

Это фактически синтезирует переменную экземпляра в Foo именем _qux , к которой обращаются сообщения getter и setter -qux и -setQux:

Я рекомендую против этого: это немного грязно, но есть одна веская причина использовать подчеркивание; а именно, для защиты от случайного прямого доступа к ivar. Если вы считаете, что можете доверять себе, помните, используете ли вы переменную экземпляра raw или метод доступа, просто сделайте это следующим образом:

 @interface Foo : Bar @property (retain) Baz *qux; @end @implementation Foo @synthesize qux; - (void)dealloc { [qux release]; [super dealloc]; } @end 

Затем, когда вы хотите получить доступ к переменной экземпляра напрямую, просто скажите qux (что переводит в self->qux в синтаксис C для доступа к элементу из указателя). Если вы хотите использовать методы доступа (которые будут уведомлять наблюдателей и делать другие интересные вещи, а также сделать вещи более безопасными и удобными в отношении управления памятью), используйте self.qux ( [self qux] ) и self.qux = blah; ( [self setQux:blah] ).

Печально то, что образец кода Apple и код шаблона отстой. Никогда не используйте его как руководство к правильному стилю Objective-C и, конечно же, никогда не используйте его в качестве руководства к правильной архитектуре программного обеспечения. 🙂

Вот еще одна причина. Без подчеркивания переменных экземпляра вы часто получаете предупреждение с параметрами self.title = title и self.rating = rating :

 @implementation ScaryBugData @synthesize title; @synthesize rating; - (id)initWithTitle:(NSString *)title rating:(float)rating { if (self = [super init]) { self.title = title; // Warning. Local declaration hides instance variable self.rating = rating; // Warning. Local declaration hides instance variable } return self; } @end 

Вы избегаете предупреждения путем переопределения переменных экземпляра:

 @implementation ScaryBugData @synthesize title = _title; @synthesize rating = _rating; - (id)initWithTitle:(NSString *)title rating:(float)rating { if (self = [super init]) { self.title = title; // No warning self.rating = rating; // No warning } return self; } @end 

в приложении didFinishLaunchingWithOptions: метод windows и viewController ivars относятся к использованию self

Нет, они не. Это ссылки на window свойств и viewController . Это точка подчеркивания, чтобы сделать ее более ясной, когда свойство используется (без подчеркивания), и когда к ивару обращаются напрямую (с подчеркиванием).

Да, это просто для того, чтобы отличить ссылку объекта. То есть, если объект передается напрямую, используйте его с подчеркиванием, иначе используйте self для ссылки на объект.

Interesting Posts

SSD очень медленный на ПК

Восстановить данные жесткого диска

Разрешить не-админам запускать программы в качестве админов

В Windows (и ПК), какой инструмент восстановления разделов является хорошим, надежным?

В этом конкретном случае существует ли разница между использованием списка инициализаторов членов и назначением значений в конструкторе?

Виртуальная функция C ++ из конструктора

Как ограничить пропускную способность, используемую IP-адресом в поле штрафа в pfSense

Одновременно использовать два разных интернет-соединения через Mobile USB Connections?

Когда использовать LinkedList над ArrayList?

Android: AsyncTask vs Service

Ответ на все включает мое имя в линии TO

Используйте трекбол для прокрутки, масштабирования и т. Д.

Как установить бета-версию Google Chrome для всех пользователей?

Запретить прокрутку тела, но разрешить прокрутку наложения

Ошибка «произошла ошибка чтения диска» в Windows XP

Давайте будем гением компьютера.