Вопрос

Хорошо, у меня такое чувство, что вы, ребята, сможете быстро указать, почему я в таком замешательстве по этому поводу, но у меня есть вопрос относительно того, почему следующее НЕ приводит к ошибке компилятора или предупреждению:

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

selectedObject является NSObject, и name так случилось, что это имя @property типа int.

Что меня озадачивает, так это то, почему компилятор вполне готов предположить, что возвращаемый результат [ self.selectedObject valueForKey:name ] относится к типу NSNumber * (без приведения его к типу) для того, чтобы связать сообщение с вызовом integerValue.

Очевидно, что KVC преобразует необъектные типы "number" в NSNumber, но у компилятора нет возможности узнать это -valueForKey: вернет NSNumber * в данном конкретном случае.

Почему это не приводит к предупреждению компилятора в соответствии с "id может не отвечать на '-integerValue'"?

Это было полезно?

Решение

Я надеюсь, что я все понял правильно:Это происходит потому, что id является “особенным”.Объекты в id тип может быть отправлен любым сообщением, которое вы хотите, компилятор не выполняет проверку, и все будет проверено во время выполнения.Или, другими словами, id type - это часть “динамической типизации” Objective-C, тогда как все остальные типы (например NSObject) являются частью “статической типизации”.

Таким образом, вы можете выбрать, где вы хотите использовать статическую типизацию, а где вы хотите использовать динамическую типизацию.Это совершенно законно - делать что-то подобное:

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

Но обычно вы вводите строки “плотно”, как NSStrings, потому что вы получаете удобство проверки статического типа во время компиляции и прибегаете к динамической типизации только там, где статическая будет мешать, как в valueForKey ситуация.

Другие советы

Время прошло, и теперь у нас есть лучший вывод типа благодаря __auto_type доступно начиная с Xcode 8.Итак, теперь вы можете сделать

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

и гораздо больше

На самом деле, мне это так понравилось, что я сделал это в виде капсулы для удобства.

pod 'SwiftyObjC'
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top