Prefixando nomes de propriedades com um sublinhado em Objective C

Eu já evitei sublinhados em meus nomes de variables, talvez um resquício dos meus dias de faculdade em Java. Então, quando eu defino uma propriedade no Objective C, isso é o que eu faço naturalmente.

// In the header @interface Whatever { NSString *myStringProperty } @property (nonatomic, copy) NSString *myStringProperty; // In the implementation @synthesize myStringProperty; 

Mas em quase todos os exemplos é feito como

 // In the header @interface Whatever { NSString *_myStringProperty } @property (nonatomic, copy) NSString *myStringProperty; // In the implementation @synthesize myStringProperty = _myStringProperty; 

Devo superar minha aversão ao sublinhado porque essa é a única maneira que deve ser feita, há uma boa razão para esse estilo ser o preferido?

Atualização: Com a síntese automática de propriedades, hoje em dia você pode deixar de fora o @synthesize e o resultado é o mesmo que se você tivesse usado

 @synthesize myStringProperty = _myStringProperty; 

que mostra claramente a preferência da Apple. Desde então aprendi a parar de me preocupar e amar o sublinhado.

Eu sempre uso sublinhados. Cria uma clara distinção entre variables ​​locais e variables ​​de instância. Também evita avisos do compilador na seguinte situação:

 @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 

EDITAR :

Depois de ter que suportar downvotes e ler os comentários, deixe-me tentar fazer o meu ponto:

A Apple recomenda que os ivars tenham o mesmo nome de sua propriedade. A Apple também recomenda que as propriedades iniciem com uma letra minúscula. E a Apple também recomenda que as variables ​​locais comecem com uma letra minúscula.

Agora você tem um problema, porque quando você lê um pedaço de código, e você vê uma variável sendo usada, você não pode dizer pela convenção de nomenclatura se esta variável é uma variável ivar ou local. Isso é uma merda. A solução é ter diferentes convenções de nomenclatura para ivars e variables ​​locais. Isso é simplesmente bom senso.

A maneira como você implementa essa convenção de nomenclatura é irrelevante. Se você realmente quiser, basta append “_WOOHAHA” aos nomes dos ivar. Eu não me importo (mas talvez outros o façam). O problema é que as pessoas que sabem o que estão fazendo decidiram usar o “prefixo de sublinhado” para os ivars. IMHO, eles tomaram a decisão certa, mesmo que sua própria empresa recomendasse outra coisa. (os desenvolvedores que estou falando são as pessoas que escrevem alguns dos principais frameworks da Apple e as classs do .NET Framework)

No final, a qualidade do código é mais importante do que seguir uma regra estúpida que nem é seguida pelas pessoas que a pregam.


Outra observação sobre o código que você mostrou: nunca use reter nas propriedades da string. Você deve usar a cópia .

Para mais informações sobre copiar / reter propriedades, consulte:

Propriedade NSString: copiar ou reter?

A convenção de nomenclatura para a variável de instância prefixada por _ agora é claramente declarada pela Apple nas “Diretrizes de codificação para o cacau”, após a revisão de 2012-02-16, com o motivo.

Certifique-se de que o nome da variável de instância descreva de forma concisa o atributo armazenado. Normalmente, você não deve acessar variables ​​de instância diretamente, em vez disso você deve usar methods de access (você acessa variables ​​de instância diretamente nos methods init e dealloc). Para ajudar a sinalizar isso, prefixe os nomes das variables ​​de instância com um sublinhado (_), por exemplo:

 @implementation MyClass { BOOL _showsTitle; } 

Se você sintetizar a variável de instância usando uma propriedade declarada, especifique o nome da variável de instância na instrução @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

A palestra no iTunes U, iPhone App Desenvolvimento CS193p Outono de 2011, ministrado por Paul Hegarty na Universidade de Stanford, também explica essa convenção.

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

Estou ciente de que essa pergunta é feita há algum tempo, mas eu mesmo fiz a mesma pergunta e queria compartilhar minhas descobertas.

A atual prática sugerida do Objective-C 2.0 é usar o mesmo nome para o ivar como propriedade. Você pode, opcionalmente, atribuir um ivar diferente na declaração @property, mas o fato de que, por padrão, os accessres sintetizados de uma propriedade acessarão o ivar com o mesmo nome que a propriedade indica que é o padrão que eles esperam que você siga.

Não importa o quê, como os objects ainda precisam enviar mensagens para eles mesmos para acessar as propriedades, é difícil confundir quando você está acessando uma propriedade ou quando está acessando diretamente o seu suporte ivar, embora usar o access a propriedades do ponto 2.0 o torne mais possível. Usar a syntax de passagem de mensagem padrão torna a intenção mais explícita, IMO.

 @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 

Seletores de reservas da Apple começam com sublinhado para seus próprios methods “privados” e isso inclui propriedades. Eu não acho que eles reservam _ para os nomes dos ivar.

Pessoalmente, eu evitaria usar underscore para iniciar qualquer tipo de nome de variável. É uma convenção opaca. E se outra pessoa usar sublinhado para locais e nenhum sublinhado por variables ​​de instância? E se você acidentalmente omitir o sublinhado em um método onde você tem um local definido com o mesmo nome?

É muito melhor tornar seus nomes locais diferentes dos seus nomes ivar. Por exemplo, em um setter, você pode usar newName ou neWValue.

É puramente uma questão de estilo.

Eu não sei quais exemplos usam o estilo ivar sublinhado. Os exemplos oficiais da Apple (por exemplo, CryptoExercise ) não prefixam os ivars com _ .

Vou apenas salientar que um novo projeto de navegação usando dados básicos usa sublinhados por padrão e torna as variables ​​privadas.

 @interface MyTestAppDelegate : NSObject  { UIWindow *window; UINavigationController *navigationController; @private NSManagedObjectContext *managedObjectContext_; NSManagedObjectModel *managedObjectModel_; NSPersistentStoreCoordinator *persistentStoreCoordinator_; } @interface RootViewController : UITableViewController  { @private NSFetchedResultsController *fetchedResultsController_; NSManagedObjectContext *managedObjectContext_; } 

A parte KVC do tempo de execução espera um nome ou um nome ivar ao usar valueForKey: em um object quando ele não consegue encontrar uma mensagem para recuperar essa variável. veja http://developer.apple.com/documentation/Cocoa/Conceptual/KeyValueCoding/Concepts/SearchImplementation.html

Se o tempo de execução se incomoda em procurar por _name e a documentação da apple menciona o _name primeiro, pode haver uma boa razão para isso. Vamos dar uma olhada em algumas classs SDK: UINavigationBar.h esta class tem sublinhados na frente de todos os ivars, UIView também … a lista continua. Bem, talvez seja assim com o novo iOS SDK e as boas classs NS * não façam coisas assim … errado; eles usam o sublinhado também nos arquivos de header.

A Apple usa o sublinhado em mensagens de API privadas e em ivars. Não consigo entender por que seus exemplos não forçam esse comportamento, especialmente quando o tempo de execução incomoda ter essa assim chamada “convenção de nomenclatura” codificada no caminho de pesquisa da variável. Seria bom ver alguma consistência.

Apenas uma nota, existe um esquema de nomenclatura estrito que você deve seguir para ser compatível com o KVC; o link acima ajuda você a se adequar a isso para usar este recurso útil do tempo de execução.