Префикс имен свойств с подчеркиванием в 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. С тех пор я научился перестать волноваться и полюбить символ подчеркивания.
Ответы
Ответ 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; ссылка выше помогает вам соответствовать этому, чтобы использовать эту удобную функцию среды выполнения.