iOS: Cómo saber si un object de tipo id es una class o un protocolo

Esto es algo bastante avanzado. Estoy jugando con un código de time de ejecución como proyecto paralelo. El problema que estoy tratando de resolver es este: si tengo un object de tipo id, y ese object puede ser una cadena o una class o un protocolo, ¿cómo puedo decir cuál es?

Por ejemplo, aquí hay un código con el que estoy jugando:

[objArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { if ([obj isKindOfClass:[NSString class]]) { // Do something with the string ... } else if (... obj is a Protocol ...) { // Do something with the protocol ... } else if (... obj is a Class ...) { // Do something with the class ... } else { // It's something we are not interested in! } }]; 

Hasta ahora no he tenido problemas para almacenar como un surtido de instancias de NSString, Class y Protocol en la matriz y todo lo demás está bien. La razón por la que necesito detectarlos es simplemente que no puedo controlar lo que entra en este código. Por lo tanto, necesito establecer qué es lo que el obj está procesando antes de hacer cosas con él.

He estado probando todo tipo de funciones de time de ejecución y cosas así, pero hasta ahora no tengo suerte si identifico cuál es el object.

¿Alguien intentó algo así?

Debido a que el protocolo es una subclass de NSObject , puede detectarlo de la misma manera que lo haría con cualquier otra class. Lo interesante es que la class de protocolo no tiene una interfaz pública.

Un object de tipo id es una Clase o una instancia de una class, por lo que probaría si es Clase primero, y si esto falla, es una instancia de una class y, por lo tanto, utilizará comparaciones de cadenas para determinar el nombre de la class. Para el protocolo, compare con @ "Protocolo"

Ejemplo-

 // assign the object to inspect id obj = //... NSString *className; // test for Class type first if (object_isClass(obj)) { // it's a Class... inspect further... className = NSStringFromClass(obj); if ([className isEqualToString:@"Protocol"]) { /* Protocol Class */ } } else { // must be an instance - get the class name className = NSStringFromClass([obj class]); // test for instance of Protocol class if ([className isEqualToString:@"Protocol"]) { /* Protocol instance */ } // continue testing for any other classes here... } 

NSStringFromClass se encuentra en Referencia de funciones de base

Puede que ahora haya encontrado la solución.

Para probar si una identificación es una class:

 NSLog(@"isClass %s", object_isClass(obj) ? "yes":"no"); 

Para probar si un id es un protocolo:

 NSLog(@"isProtocol %s", object_getClass(obj) == objc_getClass("Protocol") ? "yes":"NO"); 

Estos parecen funcionar, aunque creo que puede haber una mejor manera de hacer la verificación del protocolo.