好吧,我有一种感觉,你们可以快速指出为什么我对此感到困惑,但我有一个问题,为什么以下不会导致编译器错误或警告:< / p>
NSString * intValue = [ NSString stringWithFormat:@"int = %i", [ [ self.selectedObject valueForKey:name ] integerValue ] ];
selectedObject
是NSObject
,而name
恰好是@property
类型int
的名称。
令我困惑的是为什么编译器完全愿意假设[ self.selectedObject valueForKey:name ]
的返回结果是NSNumber *
类型(没有对其进行类型转换),以便通过调用{{来链接消息1}}。
显然,KVC将非对象“数字”类型包装到integerValue
中,但编译器无法知道NSNumber
在这种特殊情况下会返回-valueForKey:
。
为什么这不会导致编译器警告“NSNumber *
可能无法响应'id
'”?
答案 0 :(得分:10)
我希望我做对了:这是因为id
是“特殊的”。 id
类型的对象可以发送您想要的任何消息,编译器不会进行检查,所有内容都将在运行时进行检查。或者,换句话说,id
类型是Objective-C的“动态类型”部分,而所有其他类型(如NSObject
)是“静态类型”部分。
通过这种方式,您可以选择要使用静态类型的位置以及要使用动态类型的位置。做这样的事情是完全合法的:
id str1 = @"Hello";
id str2 = [str1 stringByAppendingString:@", world"];
但通常你将字符串“紧紧地”键入为NSString
,因为你可以方便地进行编译时静态类型检查,并且只能采用动态类型,而静态类型会阻碍它,就像在valueForKey
情况下。
答案 1 :(得分:4)
时间过去了,由于有了__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'