Objective-C类型推断

CIF*_*ter 8 types inference objective-c

好吧,我有一种感觉,你们可以快速指出为什么我对此感到困惑,但我有一个问题,为什么以下不会导致编译器错误或警告:

NSString * intValue = [ NSString stringWithFormat:@"int = %i", [ [ self.selectedObject valueForKey:name ] integerValue ] ];
Run Code Online (Sandbox Code Playgroud)

selectedObject是一个NSObject,name恰好是一个@property类型的名称int.

令我困惑的是为什么编译器完全愿意假设返回结果[ self.selectedObject valueForKey:name ]是类型NSNumber *(没有类型转换)以便通过调用来链接消息integerValue.

显然,KVC将非对象"数字"类型包装成NSNumber,但编译器无法知道在这种特殊情况下-valueForKey:会返回一个NSNumber *.

为什么这不会导致编译器警告" id可能不响应' -integerValue'"?

zou*_*oul 10

我希望我做对了:这是因为id"特别".该id类型的对象可以发送您想要的任何消息,编译器不会进行检查,所有内容都将在运行时进行检查.或者,换句话说,id类型是Objective-C的"动态类型"部分,而所有其他类型(例如NSObject)是"静态类型"部分.

这样,您可以选择要使用静态类型的位置以及要使用动态类型的位置.做这样的事情是完全合法的:

id str1 = @"Hello";
id str2 = [str1 stringByAppendingString:@", world"];
Run Code Online (Sandbox Code Playgroud)

但通常你会将字符串"紧密地"键入为NSStrings,因为你可以方便地进行编译时静态类型检查,并且只能采用动态类型,静态方式会阻塞它,就像在valueForKey情况中一样.


ReD*_*ion 7

时间过去了,我们现在有了更好的类型推断,这要归功于__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'"
Run Code Online (Sandbox Code Playgroud)

还有更多

事实上,我非常喜欢这个,所以为了方便起见,我把它做成了一个吊舱。

pod 'SwiftyObjC'
Run Code Online (Sandbox Code Playgroud)