Objective-C Type Inference
-
21-09-2019 - |
Domanda
Va bene, ho la sensazione che si guys'll in grado di rilevare rapidamente perché sono così confuso su questo, ma ho una domanda sul motivo per cui il seguente non si traduca in un errore di compilazione o avviso:
NSString * intValue = [ NSString stringWithFormat:@"int = %i", [ [ self.selectedObject valueForKey:name ] integerValue ] ];
selectedObject
è un NSObject
e name
sembra essere il nome di un @property
di tipo int
.
La cosa che mi ha lasciato perplesso è il motivo per cui il compilatore è perfettamente disposto a ritenere che il risultato ritorno di [ self.selectedObject valueForKey:name ]
è di tipo NSNumber *
(senza typecasting) al fine di catena il messaggio con una chiamata a integerValue
.
Ovviamente, KVC avvolge non oggetto di tipo "numero" in NSNumber
, ma non c'è modo per il compilatore a sapere che -valueForKey:
restituirà un NSNumber *
in questo caso particolare.
Perché non questo risultato in un avviso del compilatore sulla falsariga di "id
potrebbero non rispondere ai '-integerValue
'"?
Soluzione
Spero ho capito bene: Questo perché id
è “speciale”. Gli oggetti del tipo id
possono essere inviati qualsiasi messaggio che si desidera, non v'è alcun controllo fatto dal compilatore e tutto sarà controllato in fase di esecuzione. O, in altre parole, il tipo di id
è la parte “dinamica tipizzazione” di Objective-C, mentre tutti gli altri tipi (come NSObject
) sono la parte “tipizzazione statica”.
In questo modo è possibile scegliere dove si desidera utilizzare tipizzazione statica, e dove si desidera utilizzare la tipizzazione dinamica. E 'perfettamente legale per fare qualcosa di simile:
id str1 = @"Hello";
id str2 = [str1 stringByAppendingString:@", world"];
Ma di solito si digita le stringhe “strettamente” come NSString
s, perché si ottiene la comodità di fase di compilazione controllo di tipo statico e solo ricorrere alla tipizzazione dinamica, dove quello statico sarebbe ottenere nel modo, come nella situazione valueForKey
.
Altri suggerimenti
Il tempo è passato e noi abbiamo una migliore inferenza di tipo ora grazie al __auto_type
disponibile dal Xcode 8. Così ora si può fare
#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'"
In effetti, mi è piaciuto tanto che ho fatto questo come un baccello per convenienza.
pod 'SwiftyObjC'