Selector de almacenamiento como valor en un NSDictionary


¿Hay una manera de almacenar un selector en un NSDictionary, sin almacenarlo como un NSString?

Author: Josh Caswell, 2010-05-13

5 answers

SEL es solo un puntero, que se puede almacenar en un NSValue:

NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: 
                       [NSValue valueWithPointer:@selector(foo)], @"foo",
                       nil];

Para recuperar el selector, puede usar:

SEL aSel = [[dict objectForKey:@"foo"] pointerValue];
 104
Author: Georg Fritzsche,
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
2010-08-24 09:08:33

Una alternativa a la solución de Georg sería convertir el selector en un NSString antes de almacenarlo en el NSDictionary:

NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: 
                      NSStringFromSelector(@selector(foo)), @"foo",
                      nil];

SEL selector = NSSelectorFromString([dict objectForKey:@"foo"]);

Esta técnica, aunque utiliza más memoria, le da la capacidad de serializar todo el NSDictionary como una cadena a través de bibliotecas como JSONKit.

 10
Author: David H,
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
2012-02-16 02:07:34

Un NSDictionary es realmente solo un CFDictionary que retiene y libera todas las claves y valores. Si crea un CFDictionary directamente, puede configurarlo para no retener y liberar valores. Puede encasillar un CFDictionaryRef a un NSDictionary * y viceversa.

 6
Author: drawnonward,
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
2010-05-12 20:49:53

En caso de usar UILocalNotification la única forma es usar NSSelectorFromString([dict objectForKey:@"foo"]). Con valueWithPointer la aplicación se bloquea al establecer la propiedad userInfo del objeto UILocalNotification. Ten cuidado.

 3
Author: kostas,
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
2012-05-22 14:39:00

Mientras que la respuesta de Georg debería funcionar, NSValue también admite la codificación de cualquier valor utilizando una cadena de codificación de tipo Objective-C, que tiene una forma especial de representar SEL - con una ":" (a diferencia del "^v" producido por -valueWithPointer:, que se traduce en void *).
fuente: Guía de Programación en Tiempo de Ejecución de Objective-C-Codificaciones de tipo

Trabajando fuera de la solución de Georg, la mejor manera compatible con API para poner un SEL en un NSValue en un NSDictionary sería:

// store
NSDictionary *dict = @{
    @"foo": [NSValue value:&@selector(foo) withObjCType:@encode(SEL)]
};

// retrieve
SEL aSel;
[dict[@"foo"] getValue:&aSel];



La razón para manejar un SEL como su propia bestia es que los documentos lo describen como "un tipo opaco", lo que significa que su funcionamiento interno (incluso lo que es typedefd) está fuera de los límites de los programadores de aplicaciones; Apple puede mezclarlo en cualquier momento en el futuro.

Además, usar void * s para forzar al sistema a hacer lo que quieres que haga fue útil en C en los años 90, cuando la mayoría de nosotros no sabíamos nada mejor.  eres mejor que eso ahora.

El enfoque anterior solo debe usarse si la recuperación de SEL ocurre durante la duración de ejecución del programa, no debe almacenar NSDictionary en el disco.  Si necesita almacenar SELs a largo plazo (a través de lanzamientos de aplicaciones), debe seguir el enfoque de David H y convertirlo en un NSString.

 2
Author: Slipp D. Thompson,
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
2017-05-23 12:26:33