不同类型NSArray的快速计数

时间:2011-12-09 22:28:20

标签: objective-c fast-enumeration

我有这个问题here(以及关于SO的其他问题),以及有关Objective-C集合和快速枚举的Apple文档。不清楚的是,是否填充了不同类型的NSArray,并创建了一个循环:

for ( NSString *string in myArray )
    NSLog( @"%@\n", string );

这到底发生了什么?循环是否会跳过不是NSString的任何内容?例如,如果(为了参数)a UIView在数组中,当循环遇到该项时会发生什么?

5 个答案:

答案 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 *
    // ...
}