我有这个问题here(以及关于SO的其他问题),以及有关Objective-C集合和快速枚举的Apple文档。不清楚的是,是否填充了不同类型的NSArray
,并创建了一个循环:
for ( NSString *string in myArray )
NSLog( @"%@\n", string );
这到底发生了什么?循环是否会跳过不是NSString
的任何内容?例如,如果(为了参数)a UIView
在数组中,当循环遇到该项时会发生什么?
答案 0 :(得分:9)
你为什么要那样做?我认为这会导致错误和无意识的行为。如果您的数组填充了不同的元素,请改用:
for (id object in myArray) {
// Check what kind of class it is
if ([object isKindOfClass:[UIView class]]) {
// Do something
}
else {
// Handle accordingly
}
}
您在示例中所做的与
实际上是一样的for (id object in myArray) {
NSString *string = (NSString *)object;
NSLog(@"%@\n", string);
}
仅仅因为你object
(NSString *)
并不意味着string
实际上会指向一个NSString
对象。以这种方式调用NSLog()
将根据NSObject protocol调用- (NSString *)description
方法,该类在数组中引用的类可能符合也可能不符合。如果它符合,它将打印出来。否则,它会崩溃。
答案 1 :(得分:3)
你必须明白obj-c中的指针没有类型信息。即使你写NSString*
,它也只是一个编译检查。在运行时,一切都只是id
。
Obj-c运行时永远不会检查对象是否属于给定的类。您可以毫无问题地将NSNumbers放入NSString指针中。仅当您尝试调用未在对象上定义的方法(发送消息)时才会出现错误。
快速枚举如何工作?它完全相同:
for (NSUInteger i = 0; i < myArray.count; i++) {
NSString* string = [myArray objectAtIndex:i];
[...]
}
它更快,因为它在较低级别上运行。
答案 2 :(得分:2)
有趣的问题。快速枚举的最通用语法是
for ( NSObject *obj in myArray )
NSLog( @"%@\n", obj );
我相信通过做
for ( NSString *string in myArray )
NSLog( @"%@\n", string );
相反,您只是将每个对象转换为NSString
。也就是说,我相信以上相当于
for ( NSObject *obj in myArray ) {
NSString *string = obj;
NSLog( @"%@\n", string );
}
我在Apple的documentation for Fast Enumeration中找不到确切的提及,但您可以在示例中查看它,看看会发生什么。
答案 3 :(得分:2)
我刚试了一个简单的例子......这是我的代码。
NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:1];
NSNumber *number = [NSNumber numberWithInteger:6];
[array addObject:number];
[array addObject:@"Second"];
现在如果我只是记录对象,没问题。 NSNumber
实例正在转换为NSString
,但这两种方法都会响应-description
,所以它不是问题。
for (NSString *string in array)
{
NSLog(@"%@", string);
}
但是,如果我尝试在-length
上记录NSString
...
for (NSString *string in array)
{
NSLog(@"%i", string.length);
}
...它会抛出NSInvalidArgumentException
因为NSNumber
没有响应-length
选择器。长话短说,Objective-C为你提供了很多绳索。不要把它挂起来。
答案 4 :(得分:1)
由于所有NSObject都响应isKindOfClass,你仍然可以将演员阵容保持在最低限度:
for(NSString *string in myArray) {
if (![string isKindOfClass:[NSString class]])
continue;
// proceed, knowing you have a valid NSString *
// ...
}