2011-08-13 11 views
5

¿Por qué se generan avisos al llamar a métodos no declarados en una interfaz de clase utilizando medios convencionales, pero no cuando se llaman a métodos utilizando @selector? ¿Se debe a que los selectores pueden ser ejecutados por un interlocutor diferente de uno mismo?¿Por qué Xcode no se queja de los métodos no declarados al usar @selector?

Por ejemplo:

-(void) doStuff 
{ 
    [self doNow]; // Warning: instance method not found 
    SEL sel = @selector(doNow); // no warnings 
} 

-(void) doNow {} // this method is not declared in the interface 

Respuesta

13

La advertencia "no declarado selector" está desactivada por defecto. No sé por qué. Puede volver a activarlo en la Configuración de compilación.

La documentación para esta configuración se lee:

Advertir si se encuentra un "@selector (...)" expresión que se refiere a un selector no declarado. Un selector se considera no declarado si no se ha declarado ningún método con ese nombre antes de la expresión "@selector (...)", explícitamente en una declaración @interface o @protocol, o implícitamente en una sección @implementation. Esta opción siempre realiza sus comprobaciones tan pronto como se encuentra una expresión "@selector (...)", mientras que -Wselector solo realiza sus comprobaciones en la etapa final de la compilación. Esto también aplica la convención de estilo de codificación de que los métodos y selectores deben declararse antes de ser utilizados. [GCC_WARN_UNDECLARED_SELECTOR, selector -Wundeclared]

+1

+1 solo para la documentación. –

+0

Gracias. Parece inconsistente de Apple tener esta opción desactivada por defecto. –

4

Una similares question se le preguntó sobre el SO hace unas semanas.

Esto se debe básicamente a que los selectores están atrasadas. No se buscan hasta el tiempo de ejecución. Hay opciones para forzar la verificación durante la compilación. La pregunta a la que me he vinculado tiene más información sobre cómo puedes hacerlo.

2

La forma en que @selector funciona de manera predeterminada le está diciendo al compilador; créeme que tengo este método en algún lugar de mi clase. Es el mismo concepto si haces @class yourclassname en lugar de importar el archivo .h que contiene la clase.

2

Esto se debe a que el compilador necesita saber la firma del método con el fin de llamar a ella (es decir [self doNow];), debido a que una llamada de este tipo se traduce en cualquiera de una llamada a objc_msgSend o objc_msgSend_stret dependiendo de si la firma del método tiene un tipo de retorno de struct o no. (Recuerde la diferencia entre el selector (simplemente el nombre con los dos puntos, pero sin tipos) y la firma (los tipos) de un método.) Por lo tanto, debe advertir porque podría estar llamando a la función incorrecta si no lo hace no lo se

Sin embargo, al obtener un selector (@selector(...)), no necesita saber los tipos. El selector es simplemente un nombre y has proporcionado el nombre. Se trata de para qué usa el selector. Si lo usa en performSelector:, tampoco necesita conocer los tipos, porque ese método solo funciona para métodos con argumento y tipos de objetos devueltos, por lo que no hay ambigüedad. Por lo tanto, no hay necesidad de una advertencia.

Cuestiones relacionadas