Подтвердить что ты не робот

Префикс имен свойств с подчеркиванием в Objective C

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

// In the header
@interface Whatever
{
    NSString *myStringProperty
}

@property (nonatomic, copy) NSString *myStringProperty;

// In the implementation
@synthesize myStringProperty;

Но почти в каждом примере это делается как

// In the header
@interface Whatever
{
    NSString *_myStringProperty
}

@property (nonatomic, copy) NSString *myStringProperty;

// In the implementation
@synthesize myStringProperty = _myStringProperty;

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

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

@synthesize myStringProperty = _myStringProperty;

который четко показывает предпочтения Apple. С тех пор я научился перестать волноваться и полюбить символ подчеркивания.

4b9b3361

Ответ 1

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

@interface MyClass
{
    NSString *name
}

@property (nonatomic, copy) NSString *name;

- (id) initWithName:(NSString *) name;
@end

@implementation MyClass

@synthesize name;

// The following method will result in a compiler warning
// (parameter name same as ivar name)
- (id) initWithName:(NSString *) name {
   if (self = [super init]) {
      self.name = name;
   }

   return self;
}

@end

ИЗМЕНИТЬ

После того, как вам придется переносить вниз и читать комментарии, позвольте мне попытаться высказать свою мысль:

Apple рекомендует, чтобы ivars имели то же имя, что и их свойство. Apple также рекомендует, чтобы свойства начинались с строчной буквы. И Apple также рекомендует, чтобы локальные переменные начинались с строчной буквы.

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

Способ реализации этого соглашения об именах не имеет значения. Если вы действительно хотите, вы можете просто добавить "_WOOHAHA" к именам ivar. Мне все равно (но, возможно, другие будут). Дело в том, что люди, которые знают, что они делают, решили пойти с "префиксом подчеркивания" для иваров. ИМХО, они приняли правильное решение, даже если их собственная компания рекомендует что-то другое. (разработчики, о которых я говорю, - это люди, которые пишут некоторые основные платформы Apple и классы .NET Framework)

В конце концов, качество кода более важно, чем следовать глупому правилу, за которым даже не следуют люди, проповедующие его.


Еще одно замечание о коде, который вы показали: никогда не используйте сохранить свойства строки. Вы должны использовать копию.

Дополнительные сведения о свойствах копирования/сохранения по свойствам см. в разделе

Свойство NSString: скопировать или сохранить?

Ответ 2

Соглашение об именах для переменной экземпляра, предваряемой _, теперь четко указано Apple в "Руководствах по кодированию для Cocoa" после пересмотра 2012-02-16 по его причине.

Убедитесь, что имя переменной экземпляра кратко описывает хранимый атрибут. Обычно вам не нужно напрямую обращаться к переменным экземпляра, вместо этого вы должны использовать методы доступа (вы получаете доступ к переменным экземпляра непосредственно в методах init и dealloc). Чтобы сообщить это, префикс имена переменных экземпляра с подчеркиванием (_), например:

@implementation MyClass {
    BOOL _showsTitle;
}

Если вы синтезируете переменную экземпляра с использованием объявленного свойства, укажите имя переменной экземпляра в инструкции @synthesize.

@implementation MyClass
@synthesize showsTitle=_showsTitle;

https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CodingGuidelines/Articles/NamingIvarsAndTypes.html#//apple_ref/doc/uid/20001284-BAJGIIJE

Лекция в iTunes U, разработка iPhone App CS193p осенью 2011 года, которую преподавал Пол Хегарти в Стэнфордском университете, также объясняет это соглашение.

http://itunes.apple.com/itunes-u/ipad-iphone-application-development/id473757255

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

Ответ 3

Текущая предлагаемая практика Objective-C 2.0 - использовать одно и то же имя для ivar как свойство. Вы можете дополнительно назначить другой ivar в объявлении @property, но тот факт, что по умолчанию синтезированные аксессоры для свойства будут обращаться к ivar с тем же именем, что и свойство, указывает, что шаблон, который они ожидают от вас, будет следовать.

Независимо от того, что, поскольку объектам по-прежнему приходится отправлять сообщения для себя, чтобы получить доступ к свойствам, его трудно смутить, когда вы обращаетесь к свойству или когда вы напрямую обращаетесь к его базовому ivar, хотя используя доступ к свойствам 2.0 для доступа к объектам делает это более возможным. Использование стандартного синтаксиса передачи сообщений делает намерение более явным, ИМО.

@interface Foo : NSObject {
     NSNumber *bar;
} 
@property(readwrite, retain) NSNumber * bar
@end

@implementation Foo 
@synthesize bar;

-(void) baz {
   NSNumber *numberOne = [NSNumber numberWithInt: 1];   
   //Both set the value of bar through either the your custom or the synthesized setter method
   [self setBar:numberOne];  
   self.bar = numberOne; 

   //Both get the value of bar through your synthesized or your custom accessor method
   NSNumber *fooBar = [self bar];
   fooBar = self.bar;

   //Both manipulate the bar ivar directly
   bar = numberOne;
   fooBar = bar;
}
@end 

Ответ 4

Селекторы запасов Apple, начинающиеся с подчеркивания для собственных методов "private", и которые будут включать свойства. Я не думаю, что они резервируют _ для имен ivar.

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

Гораздо лучше сделать ваши локальные имена отличными от ваших имен ivar. Например, в установщике вы можете использовать newName или neWValue.

Ответ 5

Это чисто проблема стиля.

Я не знаю, какие примеры используют подчеркнутый стиль ivar. Официальные примеры Apple (например, CryptoExercise) не префикс ivars с помощью _.

Ответ 6

Я просто укажу, что по умолчанию новый проект навигации с использованием основных данных использует trailing подчеркивание и делает переменные закрытыми.

@interface MyTestAppDelegate : NSObject <UIApplicationDelegate> {

    UIWindow *window;
    UINavigationController *navigationController;

@private
    NSManagedObjectContext *managedObjectContext_;
    NSManagedObjectModel *managedObjectModel_;
    NSPersistentStoreCoordinator *persistentStoreCoordinator_;
}

@interface RootViewController : UITableViewController <NSFetchedResultsControllerDelegate> {

@private
    NSFetchedResultsController *fetchedResultsController_;
    NSManagedObjectContext *managedObjectContext_;
}

Ответ 7

Часть KVC среды выполнения ожидает либо имя, либо _name ivar при использовании valueForKey: на объекте, когда он не может найти сообщение для извлечения этой переменной. см. http://developer.apple.com/documentation/Cocoa/Conceptual/KeyValueCoding/Concepts/SearchImplementation.html

Если среда выполнения пытается найти _имя, а документация Apple упоминает имя _name, это может быть веской причиной. Давайте взглянем на некоторые классы SDK: UINavigationBar.h этот класс имеет подчеркивания перед всеми ivars, UIView тоже... список продолжается. Ну, может быть, так происходит с новым fangled IOS SDK и хорошими классами ole NS *, которые не делают вещи таким образом... неправильно; они также используют символ подчеркивания и в файлах заголовков.

Apple использует символ подчеркивания в частных сообщениях API, а также ivars. Я не могу понять, почему их примеры не вызывают такого поведения, особенно когда среда выполнения требует, чтобы это так называемое "соглашение об именах" было жестко закодировано в пути поиска переменных. Было бы неплохо увидеть некоторую согласованность.

Просто заметьте, есть строгая схема именования, которую вы должны соблюдать, чтобы соответствовать требованиям KVC; ссылка выше помогает вам соответствовать этому, чтобы использовать эту удобную функцию среды выполнения.