Pregunta

Está bien, tengo la sensación de que guys'll será capaz de señalar rápidamente por qué estoy tan confundido acerca de esto, pero tengo una pregunta de por qué el siguiente no da lugar a un error de compilación o una advertencia:

NSString * intValue = [ NSString stringWithFormat:@"int = %i", [ [ self.selectedObject valueForKey:name ] integerValue ] ];

selectedObject es un NSObject, y name pasa a ser el nombre de una @property de tipo int.

Lo que me deja perplejo es por eso que el compilador es perfectamente dispuestos a asumir que el resultado retorno de [ self.selectedObject valueForKey:name ] es de tipo NSNumber * (sin typecasting ella) con el fin de la cadena del mensaje con una llamada a integerValue.

Obviamente, KVC envuelve no-objeto tipos "número" en NSNumber, pero no hay manera para que el compilador sepa que -valueForKey: devolverá un NSNumber * en este caso particular.

¿Por qué no este resultado en una advertencia del compilador en la línea de "id puede no responder a '-integerValue'"?

¿Fue útil?

Solución

Espero que lo hizo bien: Esto se debe a id es “especial”. Objetos del tipo id se pueden enviar cualquier mensaje que desee, no hay ningún tipo de verificación realizado por el compilador y todo lo que será comprobado en tiempo de ejecución. O, en otras palabras, el tipo id es la parte “tipado dinámico” de Objective-C, mientras que todos los otros tipos (como NSObject) son la parte “tipos estáticos”.

De esta manera usted puede elegir dónde desea utilizar tipos estáticos, y en la que desea utilizar tipado dinámico. Es perfectamente legal para hacer algo como esto:

id str1 = @"Hello";
id str2 = [str1 stringByAppendingString:@", world"];

Pero por lo general se escriben las cadenas “fuerza” como NSStrings, debido a que obtiene la conveniencia de verificación estática de tipos en tiempo de compilación, y solamente utilizará el tipado dinámico, donde la estática sería ponerse en el camino, al igual que en la situación valueForKey.

Otros consejos

El tiempo es pasado y tenemos una mejor inferencia de tipos ahora gracias a la __auto_type disponible desde Xcode 8. Así que ahora usted puede hacer

#define let __auto_type const
#define var __auto_type

let a = @[@"pew pew"];
var b = 2;
b = a; //compiler warning "Incompatible pointer to integer conversion assigning to 'int' from 'NSArray *__strong const'"

mucho más

De hecho, me gustó este tanto por lo que hizo esto como una vaina para mayor comodidad.

pod 'SwiftyObjC'
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top