Selectores en Objective C


Primero, no estoy seguro de entender realmente lo que es un selector. Desde mi punto de vista, es el nombre de un método, y puede asignarlo a una clase de tipo 'SEL' y luego ejecutar métodos como respondToSelector para ver si el receptor implementa ese método. ¿Puede alguien ofrecer una mejor explicación?

En segundo lugar, a este punto, tengo el siguiente código:

NSString *thing = @"Hello, this is Craig";

SEL sel = @selector(lowercaseString:);
NSString *lower = (([thing respondsToSelector:sel]) ? @"YES" : @"NO");
NSLog (@"Responds to lowercaseString: %@", lower);
if ([thing respondsToSelector:sel]) //(lower == @"YES")
    NSLog(@"lowercaseString is: %@", [thing lowercaseString]);

Sin embargo, a pesar de que thing es claramente una especie de NSString, y debe responder a la baja tensión, no puedo obtenga el condicional' respondsToSelector 'para devolver "SÍ"...

Author: Keavon, 2009-04-10

8 answers

Hay que tener mucho cuidado con los nombres de los métodos. En este caso, el nombre del método es simplemente "lowercaseString", no "lowercaseString:" (tenga en cuenta la ausencia de dos puntos). Es por eso que se te devuelve NO, porque los objetos NSString responden al mensaje lowercaseString pero no al mensaje lowercaseString:.

¿Cómo sabes cuándo agregar dos puntos? Se añaden dos puntos al nombre del mensaje si se añaden dos puntos cuando se llama, lo que sucede si toma un argumento. Si toma cero argumentos (como es el caso con lowercaseString), entonces no hay colon. Si toma más de un argumento, debe agregar los nombres de los argumentos adicionales junto con sus dos puntos, como en compare:options:range:locale:.

También puede mirar la documentación y notar la presencia o ausencia de dos puntos finales.

 171
Author: Adam Rosenfield,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-04-10 19:42:32

Eso es porque quieres @selector(lowercaseString), no @selector(lowercaseString:). Hay una diferencia sutil: la segunda implica un parámetro (note los dos puntos al final), pero - [NSString lowercaseString] no toma un parámetro.

 9
Author: mipadi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-04-10 19:44:13

Los selectores son una manera eficiente de hacer referencia a los métodos directamente en el código compilado - el compilador es lo que realmente asigna el valor a un SEL.

Otros ya han cubierto la segunda parte de su q, el ':' al final coincide con una firma diferente de lo que está buscando (en este caso, esa firma no existe).

 8
Author: dstnbrkr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-30 13:40:00

En este caso, el nombre del selector es incorrecto. El colon es parte de la firma de método; esto significa que el método toma un argumento. Creo que quieres

SEL sel = @selector(lowercaseString);
 5
Author: mkb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-04-10 19:41:58

El método de

NSString es lowercaseString (0 argumentos), no lowercaseString: (1 argumento).

 3
Author: Nicholas Riley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-04-10 19:42:42

No piense en los dos puntos como parte del nombre de la función, piense en él como un separador, si no tiene nada que separar (sin valor para ir con la función), entonces no lo necesita.

No estoy seguro de por qué, pero todo esto OO cosas parece ser ajeno a los desarrolladores de Apple. Yo sugeriría fuertemente agarrar Visual Studio Express y jugar con eso también. No porque uno sea mejor que el otro, simplemente es una buena manera de ver los problemas de diseño y las formas de pensamiento.

Como

introspection = reflection
+ before functions/properties = static
- = instance level

Siempre es bueno ver un problema de diferentes maneras y la programación es el rompecabezas definitivo.

 1
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-04-11 12:05:47

Según mi comprensión de la documentación de Apple, un selector representa el nombre del método que desea llamar. Lo bueno de los selectores es que puede usarlos en casos en los que el método exacto a llamar varía. Como un ejemplo simple, puedes hacer algo como:

SEL selec;
if (a == b) {
selec = @selector(method1)
}
else
{
selec = @selector(method2)
};
[self performSelector:selec];
 0
Author: moonman239,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-16 23:30:27

Según los documentos de apple: https://developer.apple.com/library/archive/documentation/General/Conceptual/DevPedia-CocoaCore/Selector.html

Un selector es el nombre utilizado para seleccionar un método a ejecutar para un objeto, o el identificador único que reemplaza el nombre cuando se compila el código fuente. Un selector por sí mismo no hace nada. Simplemente identifica un método. Lo único que hace que el nombre del método selector sea diferente de una cadena simple es que el compilador se asegura de que los selectores sean únicos. Lo que hace que un selector sea útil es que (junto con el tiempo de ejecución) actúa como un puntero de función dinámica que, para un nombre dado, apunta automáticamente a la implementación de un método apropiado para cualquier clase con la que se use. Supongamos que tiene un selector para el método run, y las clases Dog, Athlete y ComputerSimulation (cada una de las cuales implementó un método run). El selector podría usarse con una instancia de cada una de las clases para invocar su ejecución método-aunque la implementación puede ser diferente para cada uno.

Ejemplo: (lldb) breakpoint selector set selector viewDidLoad

Esto establecerá un punto de interrupción en todas las implementaciones de viewDidLoad en su aplicación. Selector es una especie de identificador global para un método.

 0
Author: Sergheev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-10 10:53:30