iphone objective-c coding-style

iphone - Prefijo de nombres de propiedades con un guión bajo en Objective C



objective-c coding-style (7)

Apple reserva selectores que comienzan con guiones bajos para sus propios métodos "privados" y que incluirían propiedades. Sin embargo, no creo que reserven _ para nombres de ivar.

Personalmente, me mantendría alejado del uso del guión bajo para comenzar cualquier tipo de nombre de variable. Es una convención opaca. ¿Qué sucede si alguien más utiliza un guión bajo para los locales y ningún guión bajo para las variables de instancia? ¿Qué pasa si accidentalmente omite el guión bajo en un método donde tiene un local definido con el mismo nombre?

Es mucho mejor hacer que sus nombres locales sean diferentes de sus nombres. Por ejemplo, en un setter puede usar newName o neWValue.

Anteriormente evité los guiones bajos en mis nombres de variables, tal vez un remanente de mis días universitarios en Java. Entonces, cuando defino una propiedad en Objective C, esto es lo que hago naturalmente.

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

Pero en casi todos los ejemplos se hace como

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

¿Debería superar mi aversión al subrayado porque esa es la única forma en que debería hacerse, ¿hay alguna buena razón para que este estilo sea el preferido?

Actualización: con la síntesis de propiedad automática hoy en día puede omitir @synthesize y el resultado es el mismo que si hubiera usado

@synthesize myStringProperty = _myStringProperty;

que muestra claramente las preferencias de Apple. Desde entonces aprendí a dejar de preocuparme y amo el guión bajo.


Es puramente un problema de estilo.

No sé qué ejemplos usan el estilo ivar subrayado. Los ejemplos oficiales de Apple (p. Ej., CryptoExercise ) no preceden a los ivars con _ .


La convención de nomenclatura para la variable de instancia con el prefijo _ ahora está claramente establecida por Apple en las "Directrices de codificación para el cacao", después de la revisión de 2012-02-16, con su razón.

Asegúrese de que el nombre de la variable de instancia describa concisamente el atributo almacenado. Por lo general, no debe acceder directamente a las variables de instancia, sino que debe usar métodos de acceso (se accede directamente a las variables de instancia en los métodos init y dealloc). Para ayudar a señalizar esto, prefija nombres de variable de instancia con un guión bajo (_), por ejemplo:

@implementation MyClass { BOOL _showsTitle; }

Si sintetiza la variable de instancia utilizando una propiedad declarada, especifique el nombre de la variable de instancia en la instrucción @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

La conferencia en iTunes U, iPhone App Development CS193p Otoño 2011 impartida por Paul Hegarty en la Universidad de Stanford, también explica esta convención.

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

Soy consciente de que hace bastante tiempo hace esta pregunta, pero yo mismo tenía la misma pregunta y quería compartir mis hallazgos.


La parte de KVC del tiempo de ejecución espera un nombre o _name ivar cuando usa valueForKey: en un objeto cuando no puede encontrar un mensaje para recuperar esa variable. ver http://developer.apple.com/documentation/Cocoa/Conceptual/KeyValueCoding/Concepts/SearchImplementation.html

Si el tiempo de ejecución molesta en buscar _name y la documentación de apple menciona el _name primero, puede haber una buena razón para esto. Echemos un vistazo a algunas clases de SDK: UINavigationBar.h esta clase tiene subrayado delante de todos los ivars, UIView también ... la lista continúa. Bueno, tal vez sea así con el nuevo iOS SDK y las buenas clases NS NS * no hacen thinges de esa manera ... mal; también usan el guión bajo en los archivos de encabezado.

Apple usa el guión bajo en mensajes API privados así como ivars. No puedo entender por qué sus ejemplos no impulsan este comportamiento, especialmente cuando el tiempo de ejecución se molesta en tener esta llamada "convención de nomenclatura" codificada en la ruta de búsqueda de variables. Sería bueno ver algo de coherencia.

Solo una nota, hay un esquema estricto de nombres que debes seguir para cumplir con KVC; el enlace de arriba le ayuda a conformarse a esto para usar esta práctica función del tiempo de ejecución.


La práctica actual sugerida de Objective-C 2.0 es usar el mismo nombre para el ivar como propiedad. Opcionalmente, puede asignar un ivar diferente en la declaración @property, pero el hecho de que, de forma predeterminada, los descriptores de acceso sintetizados de una propiedad accedan al ivar con el mismo nombre que la propiedad indica que ese es el patrón que esperan que siga.

No importa qué, dado que los objetos aún tienen que enviarse mensajes para acceder a las propiedades, es difícil confundir cuando se accede a una propiedad o cuando se accede directamente a su respaldo ivar, aunque usando el acceso de punto 2.0 a las propiedades lo hace más posible. El uso de la sintaxis estándar de paso de mensajes hace que el intento sea más explícito, 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


Siempre uso subrayados. Crea una distinción clara entre variables locales y variables de instancia. También evita las advertencias del compilador en la siguiente situación:

@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 :

Después de tener que soportar downvotes y leer los comentarios, permítanme intentar hacer mi punto:

Apple recomienda que los ivars tengan el mismo nombre que su propiedad. Apple también recomienda que las propiedades comiencen con una letra minúscula. Y Apple también recomienda que las variables locales comiencen con una letra minúscula.

Ahora tiene un problema, porque cuando lee un fragmento de código y ve que se usa una variable, no puede decir por la convención de nomenclatura si esta variable es una variable ivar o local. Eso apesta. La solución es tener diferentes convenciones de nomenclatura para ivars y variables locales. Eso es simplemente sentido común.

La forma en que implementa esta convención de nomenclatura es irrelevante. Si realmente lo desea, simplemente puede agregar "_WOOHAHA" a los nombres de ivar. No me importa (pero tal vez otros lo harán). La cuestión es que las personas que saben lo que hacen han decidido usar el "prefijo de subrayado" para ivars. En mi humilde opinión, tomaron la decisión correcta, incluso si su propia empresa recomienda algo más. (Los desarrolladores de los que estoy hablando son las personas que escriben algunos de los principales frameworks de Apple y las clases de .NET Framework)

Al final, la calidad del código es más importante que seguir una regla estúpida que ni siquiera siguen las personas que la predican.

Otro comentario sobre el código que ha mostrado: nunca use retener en las propiedades de la cadena. Deberías usar copiar en su lugar.

Para obtener más información sobre cómo copiar / retener propiedades, consulte:

Propiedad NSString: ¿copiar o retener?


Solo señalaré que un nuevo proyecto de navegación que utiliza datos centrales usa guiones bajos finales de forma predeterminada y hace que las variables sean privadas.

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