Pergunta

Ok, tenho a sensação de que vocês serão capazes de apontar rapidamente por que estou tão confuso sobre isso, mas tenho uma pergunta sobre por que o seguinte não resulta em um erro do compilador ou aviso:

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

selectedObject é um NSObject, e name acontece que é o nome de um @property do tipo int.

O que me perplexos é por que o compilador está perfeitamente disposto a assumir que o resultado de retorno de [ self.selectedObject valueForKey:name ] é do tipo NSNumber * (sem digitá -lo) para encadear a mensagem com uma chamada para integerValue.

Obviamente, o KVC encerra tipos de "número" de objeto em NSNumber, mas não há como o compilador saber que -valueForKey: Vai devolver um NSNumber * neste caso em particular.

Por que isso não resulta em um aviso de compilador ao longo das linhas de "id pode não responder a '-integerValue'"?

Foi útil?

Solução

Espero ter acertado: isso é porque id é "especial". Objetos do id O tipo pode receber qualquer mensagem que você desejar, não há verificação feita pelo compilador e tudo será verificado no tempo de execução. Ou, em outras palavras, o id Tipo é a parte "dinâmica de digitação" do Objective-C, enquanto todos os outros tipos (como NSObject) são a parte da "digitação estática".

Dessa forma, você pode escolher onde deseja usar digitação estática e onde deseja usar a digitação dinâmica. É perfeitamente legal fazer algo assim:

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

Mas geralmente você digita as cordas "firmemente" como NSStrings, porque você obtém a conveniência da verificação do tipo estático no tempo de compilação e só recorda a uma digitação dinâmica onde o estático atrapalharia, como no valueForKey situação.

Outras dicas

O tempo é passado e temos melhor inferência de tipo agora graças ao __auto_type Disponível desde o Xcode 8. Então agora você pode fazer

#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'"

e muito mais

Na verdade, eu gostei tanto disso, então fiz isso como um pod por conveniência.

pod 'SwiftyObjC'
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top