0
NSMutableArray *array = [[NSMutableArray alloc] init];
NSString *string = @"string";
[array addObject:string];
NSDate *date = [[NSDate alloc] init];
[array addObject:date];

    for (*placeholder* stuff in array)
        NSLog(@"one");

如果我将占位符更改为 NSString* 或 NSDate*,我希望看到“one”,因为 for 循环应该忽略不匹配的类型。但是,结果是“一个”。

这是否意味着无论情况如何,您都应该只使用占位符id ,因为无论如何它似乎并不重要?

4

3 回答 3

3

快速枚举总是遍历集合中的所有对象。它不过滤。

唯一发生的事情是,你会有一些奇怪的演员阵容。

如果您的数组包含不同类的对象,您可以确定每个对象的类isMemberOfClass:


如果你愿意for (NSDate *obj in array),数组中的任何对象都将被强制转换为 NSDate,无论它是否是有感觉的。并且由于objective-c的性质,它甚至可以工作,只要您不发送只能被NSDate对象理解的消息或将对象作为参数发送给需要接收日期对象的方法,作为cast 无论如何都不会改变对象。强制转换只是您对编译器做出的承诺,即您知道自己在做什么。其实你也可以称之为谎言。


要回答您的问题标题本身:您不必在循环语句中设置类。通用对象类型id就足够了。但通常你在数组中有一种对象——视图、数字、字符串、日期……。通过声明正确的类,您可以获得一些舒适感,例如更好的自动完成功能。

于 2013-03-06T11:08:13.907 回答
1

是的,使用id(或其他一些共同的祖先类)是正确的方法,然后有必要确定枚举了哪种类型的类以便以不同的方式处理它:

for (id obj in array)
{
    if ([obj isMemberOfClass:[NSString class]])
    {
        NSString *str = (NSString *)obj;
        NSLog("obj is a string: %@", str);
    }
    else if ([obj isMemberOfClass:[NSDate class]])
    {
        NSDate *date = (NSDate *)obj;
        NSLog("obj is a date: %@", date);
    }
}
于 2013-03-06T11:10:27.557 回答
0

这个问题与快速枚举无关,而是与可以包含任何类型对象的集合有关。当您访问数组的单个元素时会出现同样的问题:

id lastObject = [array lastObject];

或者

NSString *string = [array lastObject];

你会选择哪个?这完全取决于您的代码。如果您确定array它只包含字符串,那么在我看来,最好使用第二种选择,因为您可以从编译器获得额外的类型检查、自动完成和方法匹配(即,如果您调用对两个不同对象具有不同签名的方法)。这同样适用于快速枚举:如果您的集合可以包含任何类型的对象,请使用id. 如果您知道它包含什么,请使用特定类型。(同样也适用于块测试。在NSArray's 方法

- (NSUInteger)indexOfObjectPassingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate

例如,如果您知道它仅包含字符串,则可以在块参数中替换id为。NSString *它不会改变所有编译的代码或应用程序的行为,它只会改变编译器类型检查。

于 2013-03-06T11:25:48.923 回答