Iphone 没有id的警告?

Iphone 没有id的警告?,iphone,objective-c,xcode,cocoa-touch,Iphone,Objective C,Xcode,Cocoa Touch,我刚刚发现了一些令我有点困惑的事情,不知是否有人能帮我澄清一下 NSArray *nextArray = [NSArray arrayWithObjects:@"ONE", @"TWO", @"THREE", nil]; for(id eachObject in nextArray) { NSLog(@"COUNT: %d", [eachObject length]); } 为什么上面没有抱怨/警告我询问id的长度这一事实?编译器永远不会键入发送到id的检查消息。这部分是Objecti

我刚刚发现了一些令我有点困惑的事情,不知是否有人能帮我澄清一下

NSArray *nextArray = [NSArray arrayWithObjects:@"ONE", @"TWO", @"THREE", nil];
for(id eachObject in nextArray) {
    NSLog(@"COUNT: %d", [eachObject length]);
}

为什么上面没有抱怨/警告我询问id的长度这一事实?

编译器永远不会键入发送到id的检查消息。这部分是Objective-C的活力所在


如果eachObject是任何其他类型,那么如果编译器无法解析方法名,就会出现错误

Objective-C中的每个对象都知道它有什么类,以及它是否能够处理消息。检查类的不是编译器,而是运行时的对象本身


对象的类在编译器时可以不定义,但在运行时每个对象都有一个已定义的类。

简单地说,id表示所有Objective-C类。因此,length方法属于NSString类。编译器不会向您发出警告。
id在运行时动态确定,在编译时未知。

在Objective-C
中,id
是任何类型的对象的通用类型,不考虑类,可以用于类的实例和类对象本身。
id
类型是完全非限制性的,它没有关于对象的信息,只是它是一个对象。因此,编译器无法知道该对象是否能够响应某个方法,因为它不知道它是什么类型的对象。
通过在代码中使用它,您基本上是在说“无论它指向什么,执行这个操作”

NSArray可能包含不同的对象类型,例如:

NSArray *thArray = [[NSArray alloc] initWithObjects:@"Stack",@"Overflow",[NSNumber numberWithInt:10],nil];
for(id theObject in thArray) {
    NSLog(@"COUNT: %lu", [theObject length]);
}
id
可以表示任何对象(在本例中为
NSString
NSNumber
),

因此,编译器无法知道基元方法
length
是否存在

当您特别不希望进行编译器类型检查时,可以使用
id
。您可以向
id
类型发送任何消息而不发出警告,也可以将
id
分配给任何其他类型而不进行类型转换

这允许您从数组中获取对象,而无需使用强制转换。例如,您可以自由假设数组包含NSString:

NSString* someString = [myArray objectAtIndex:1];
它还允许您向对象发送消息,而无需强制转换或警告。事实上,您希望发送的消息可能不是任何正式类或协议的一部分:

id someObject = [myArray objectAtIndex:1];
if ([someObject respondsToSelector:@selector(setName:)])
{
    [someObject setName:@"Foo"];
}

因为(id)可以是任何NSObject。就像一个可以有长度的NSString。@大力水手:甚至不需要是NSObject。可以从Nproxy或某些完全不同的基类继承。虽然在实践中,几乎所有东西都至少符合NSObject协议。啊,我明白了,我知道id可以是任何Objective-C类,但我一直认为在尝试访问它之前必须检查类型和强制转换。非常感谢。回答得很好,但有一点您可能需要更正:
length
不是一个属性。哎呀,愚蠢的错误,用
基本方法
替换了
属性。谢谢:)谢谢,如果([theObject respondsToSelector:@selector(length)]{…这可能值得添加,以防有人认为代码在运行时可以工作。