9

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

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

selectedObject是 a NSObject,并且name恰好是 a@property类型的名称int

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

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

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

4

2 回答 2

11

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

这样你就可以选择你想在哪里使用静态类型,以及你想在哪里使用动态类型。这样做是完全合法的:

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

但是通常您将字符串“严格”键入为NSStrings,因为您可以获得编译时静态类型检查的便利,并且只在静态类型会妨碍的情况下使用动态类型,例如在这种valueForKey情况下。

于 2010-01-16T08:26:15.737 回答
8

时间过去了,我们现在有了更好的类型推断,这要归功于__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'
于 2018-07-05T07:27:59.483 回答