Selectores en Objective-C?

122

Primero, no estoy seguro de entender realmente qué es un selector. Según tengo entendido, 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. ¿Alguien puede ofrecer una mejor explicación?

En segundo lugar, hasta 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 thinges claramente un tipo de NSString, y debería responder a minúsculasString, no puedo obtener el condicional 'respondsToSelector' para devolver "SÍ" ...

Craig
fuente
Desea leer la descripción del Selector en el sitio de desarrolladores de Apple: Selectores .
lothar
14
Stanford curso CS193P tarea 1B? ¡Tengo exactamente la misma pregunta aquí! :)
Corstian Boerman

Respuestas:

181

Debes tener mucho cuidado con los nombres de los métodos. En este caso, el nombre del método es " lowercaseString", no " lowercaseString:" (tenga en cuenta la ausencia de los dos puntos). Es por eso que te NOdevuelven, porque los NSStringobjetos responden al lowercaseStringmensaje pero no al lowercaseString:mensaje.

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

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

Adam Rosenfield
fuente
12

Los selectores son una forma eficiente de hacer referencia a 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 a la que está buscando (en este caso, esa firma no existe).

dstnbrkr
fuente
10

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

mipadi
fuente
5

En este caso, el nombre del selector es incorrecto. Los dos puntos aquí son parte de la firma del método; significa que el método toma un argumento. Creo que quieres

SEL sel = @selector(lowercaseString);
mkb
fuente
3

El método de NSString es lowercaseString(0 argumentos), no lowercaseString:(1 argumento).

Nicholas Riley
fuente
1

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 (ningún valor para ir con la función), entonces no lo necesita.

No estoy seguro de por qué, pero todo esto OO parece ser extraño para los desarrolladores de Apple. Sugeriría encarecidamente tomar Visual Studio Express y jugar con eso también. No porque uno sea mejor que el otro, solo es una buena manera de ver los problemas de diseño y las formas de pensar.

Me gusta

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

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


fuente
0

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

SEL selec;
if (a == b) {
selec = @selector(method1)
}
else
{
selec = @selector(method2)
};
[self performSelector:selec];
moonman239
fuente
0

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í solo 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ámico que, para un nombre dado, apunta automáticamente a la implementación de un método apropiado para la clase con la que se utiliza. Suponga que tiene un selector para la ejecución del método y las clases Dog, Athlete y ComputerSimulation (cada una de las cuales implementó una ejecución del método).

Ejemplo: (lldb) punto de interrupción --set selector viewDidLoad

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

Adrian
fuente