2010-03-29 7 views
25

estoy usando el siguiente código ...convención de Objective-C para evitar "local declaración esconde variable de instancia", advirtiendo

-(id) initWithVariableName:(NSString*)variableName withComparisonValue:(NSString*)comparisonValue { 

    // super init 
    self = [super init]; 
    if (!self) return nil; 

    // set instance variables 
    self.mustExist = NO; 
    self.reverseCondition = NO; 
    self.regularExpression = NO; 
    self.variableName = variableName; // generates warning 
    self.comparisonValue = comparisonValue; // generates warning 

    return self; 
} 

que generó los dos siguientes advertencias ...

  • Declaración local de 'variableName' esconde variable de instancia
  • Declaración local de 'comparisonValue' esconde instancia de variable

¿Existe una convención común o aceptada para tratar estas advertencias?

Entiendo que es simplemente para informar al usuario que debe especificar una instancia al referirse al miembro de la clase, pero es molesto.

+0

es sólo una advertencia. simplemente puede ignorarlo – newacct

+0

No es siquiera un problema en este ejemplo, ya que está accediendo a todas sus variables de instancia a través de la sintaxis de punto. Incluso si utilizara la sintaxis convencional de eliminación de struct ('self-> variableName') no habría ningún problema. Esta advertencia solo le dice que no puede usar 'variableName' por sí mismo para referirse a la variable de instancia. – codewarrior

+4

¿No hay un pragma para desactivar esta advertencia? Odio el código feo – mxcl

Respuesta

28

Lamentablemente, no existe una "buena" forma de prevenir este error. El patrón común es el uso de un nombre de parámetro poco estúpido como

-(id) initWithVariableName:(NSString*)theVariableName 
     withComparisonValue:(NSString*)theComparisonValue { 
    self.variableName = theVariableName; 
    self.comparisonValue = theComparisonValue; 

    return self; 
} 
+6

Prefiero initialVariableName, yo mismo. – codewarrior

+0

@codewarrior Oooh, buena idea. Eso también me gusta más. Los documentos de Apple a menudo usan 'theX', pero' initialX' es más descriptivo. –

+5

Se vuelve ridículo cuando tienes initialMiddleInitial, etc. – codewarrior

1

usted debe variables de instancia general prefijo con algo así como un guión bajo (por ejemplo _variableName) para evitar las advertencias del compilador como este.

De lo contrario, cambie ligeramente los nombres en la firma de su método, no hay una convención de nomenclatura definida.

+1

Apple desaconseja usar guiones bajos para esto, porque usan esta notación para sus variables de instancia privadas. – Chuck

+0

Buen punto, tal vez un prefijo un poco más único sería más agradable. – indragie

+0

@Chuck - Apple desaconseja usar ivars con el guión bajo inicial (o variables con alcance estático), pero las variables automáticas como esta deberían estar bien. Como no compila en los encabezados privados, no recibirá la advertencia, y dado que no está (o no debería estar) accediendo a esos ivars de todos modos, el alcance automático que enmascara el ivar no es un problema. –

3

O bien otorgue al local un nombre más descriptivo (por ejemplo, initialVariableName) o proporcione a las variables de instancia una notación diferente (por ejemplo, myClass_variableName). Prefiero esto último en la mayoría de los casos porque llama la atención cuando uso elementos internos de clase en lugar de la interfaz adecuada.

4

Si su método realmente es un inicializador, no olvide hacer su self = [super init];.

- (id) initWith... 
{ 
    self = [super init]; 
    if (!self) return nil; 

    // do stuff 

    return self; 
} 

nunca he encontrado personalmente una situación en la self ha cambiado a nil u otro valor, pero es la Objective-C initialiser Idiom ™.

+0

Sabía que había algo como eso que hacer ... pero este era un código de "relleno" realmente rápido que aún no se ha desarrollado :) Gracias por las cabeceras :) – Nippysaurus

+0

Actualicé el código del ejemplo con tus comentarios :) – Nippysaurus

+1

Es mejor verificar (auto) y el código de progreso dentro de ese bloque que usar 2 declaraciones de retorno. Si [superiniciar] está dando un nulo, el auto será nulo y se devuelve de todos modos en la parte inferior del método. – Justin

32

Veo que esta es una pregunta bastante antigua con una respuesta aceptada, pero tengo una mejor solución y su convención de código.

La convención establece que prefija variables privadas con un guión bajo (_varName) y public (como propiedades) con solo el nombre.

Con esto, puede llamar al mismo nombre de variable en sus funciones.

Ejemplo:

ExampleClass.h

@interface ExampleClass : NSObject 
{ 
    NSString *_varName; //this is not required if you create a property 
} 

@property (nonatomic, retain) NSString *varName; 

- (void)someMethodWithVarName:(NSString *)varName; 

@end 

ExampleClass.m

#import "ExampleClass.h" 

@implementation ExampleClass 

@synthesize varName = _varName; //if you don't declare the _varName in the header file, Objective-C does it for you. 

- (id)init 
{ 
    self = [super init]; 
    if (self) { 
     // Initialization code here. 
    } 

    return self; 
} 

- (void)someMethodWithVarName:(NSString *)varName 
{ 
    _varName = varName; //just for example purpose 
} 

@end 
+1

Ahora sé por qué en ese libro de directx que he leído todas las variables de instancia tienen el prefijo m. Al igual que mVB, mNumRows, etc. ... –

+0

Esta sería una buena convención. ¡Gracias! –

+1

Esta es la convención popular en otros idiomas. También me gustaría mencionar que ** Apple Coding Guidelines ** permite usar un carácter de subrayado como prefijo para una variable de instancia (ver convenciones tipográficas [aquí] (http://developer.apple.com/library/mac/#documentation /Cocoa/Conceptual/CodingGuidelines/Articles/NamingBasics.html)) – Vlad

3

Aunque es cuestión de edad, pero todavía tengo una buena solución para suprimir la advertencia en código

-(id) initWithVariableName:(NSString*)variableName withComparisonValue:(NSString*)comparisonValue { 

    // super init 
    self = [super init]; 
    if (!self) return nil; 

    // set instance variables 
    self.mustExist = NO; 
    self.reverseCondition = NO; 
    self.regularExpression = NO; 


    #pragma GCC diagnostic push 
    #pragma GCC diagnostic ignored "-Wshadow-ivar" 
    self.variableName = variableName; // generates warning 
    self.comparisonValue = comparisonValue; // generates warning 
    #pragma GCC diagnostic pop 



    return self; 
} 

Usted puede aprender sobre GCC pragma here y para obtener el código de advertencia de una advertencia ir al registro Navigator (Comando + 7), seleccione la construcción superior, ampliar el registro (el botón '=' a la derecha), y desplazarse hasta la parte inferior y no su código de advertencia es entre corchetes como esto [-Wshadow-ivar]


Editar

Para sonido metálico puede utilizar

#pragma clang diagnostic push 
#pragma clang diagnostic ignored "-Wshadow-ivar" 
// your code 
#pragma clang diagnostic pop 
+0

Gracias. A veces, solo quiero que el nombre sea el mismo. – mxcl

+0

Sí, para un usuario antiguo de Java que tenga el mismo nombre en el ctor parametrizado se recomienda –

2
_varName = varName; 

Puede utilizar sólo esta pero sin la @synthesize - cada vez que desee utilizar esa variable que acaba de escribir _*variable name* y se elimina el error

2

Esto no es un problema en absoluto en el moderno Objective-C. En el Objective-C moderno, las propiedades se sintetizan automáticamente y sus variables de instancia correspondientes obtienen un prefijo _.

Por lo tanto, con la auto-síntesis sus propiedades crearían variables de instancia _variableName y _comparisonValue. No se producen sombras en este caso.

Más información en este blog post


Si es absolutamente necesario para sintetizar manualmente sus propiedades, cambiar el nombre del Ivar sinthesized como esto

@synthesize variableName = _variableName; 

En caso general, cambiar el nombre de los argumentos del método .

0

Si está utilizando el nombre de la variable de instancia local igual que el nombre de la variable de instancia global, se produce esta advertencia.

Primer método: Para ignorar esta advertencia, use cambiar el nombre de la variable de instancia local o cambie el nombre de la variable de instancia global.

Segunda Methode: si desea utilizar la variable global a continuación, llamar como self->variableName

-(id) initWithVariableName:(NSString*)variableName withComparisonValue:(NSString*)comparisonValue { 

    // super init 
    self = [super init]; 
    if (!self) return nil; 

    // set instance variables 
    self->variableName = variableName; //point to global variableName 
    self->comparisonValue = comparisonValue; //point to global comparisonValue 

    return self; 
} 
Cuestiones relacionadas