【问题标题】:In Objective-C how to deal with NSArray of related objects在Objective-C中如何处理相关对象的NSArray
【发布时间】:2013-08-27 12:07:02
【问题描述】:

Animal 是一个具有BOOL 属性的类,称为aliveMonkeyZebraWalrusAnimal 的子类。如果我有一个名为zooNSArray 实例,其中包含MonkeyZebraWalrus 的混合实例,并且我想找到第一个活着的Zebra 实例,我可能会这样做像这样:

Zebra *zebra; 
for (Animal *animal in zoo) {
    if ([animal isMemberOfClass:[Zebra class]] && animal.alive) {
        zebra = animal;
        break;
    }
}

问题是当我设置zebra = animal 时编译器抱怨指针类型不兼容。如果我做一些像zebra = (Zebra *)animal 这样的转换,那么它似乎可以工作,但我不确定这种转换在Objective-C 中是否安全。

处理这种情况的更好方法是什么?

【问题讨论】:

  • 这种类型的转换在这里很好,因为您已经测试了anmimalZebra 类型的蜜蜂。无论如何,从长远来看,isKindOfClass 可能会更省钱,因为这也会为Zebra 的每个潜在(未来)子类返回 YES。
  • Zebra,您的示例的编写方式,如果集合中没有 Animal 实例同时属于类 Zebraalive,则未定义。

标签: objective-c cocoa nsarray subclassing


【解决方案1】:

您遇到了“是”问题。

如果您将zebra 分配给animal,则不会有问题,因为zebra 的类是Zebra,它“是”Animal

但是根据您的操作,您将animal 分配给zebra,但animal 属于Animal 类,即超类。 "is a" 测试失败,但进行了简单的转换:

zebra = (Zebra *)animal;

负责编译器警告。是的,它很安全。

这是做同样事情的更现代的方式。顺便说一句,由于在最后一行,-objectAtIndex: 返回id,所以不会出现上述问题:

NSUInteger index = [zoo indexOfObjectPassingTest:^BOOL(Animal *animal, NSUInteger idx, BOOL *stop) {
    return ([animal isMemberOfClass:[Zebra class]] && animal.alive);
}];
Zebra *zebra = (index != NSNotFound) ? [zoo objectAtIndex:index] : nil;

请注意,我确实将块的参数之一从 id obj 调整为 Animal *animal;如果您知道您的集合仅包含对 Animal 实例的引用,那么您当然可以这样做。

【讨论】:

  • +1。不过,“现代”方式可能更慢。它的最好情况是O(n),它等于OP代码最坏情况。在任何情况下,循环和中断都会更高效,唯一的例外是在最后一次迭代中找到了 zebra 对象。
【解决方案2】:

这绝对是在 Objective-C 中做到这一点的方式。如果您正在检查它是您首先选择的那种类,那么它非常安全。即使将其“键入”到其他内容,isMemberOfClass 也会使用运行时报告它真正是什么。

【讨论】:

    【解决方案3】:

    完成相同任务的另一种方法。

    [zoo enumerateObjectsusingBlock:^(id obj, NSUInteger index, BOOL *stop){
        if ([obj isMemberOfClass:[Zebra class] && animal.alive){
            zebra = (Zebra *)animal;
            *stop = YES;
        }
    }];
    

    顺便说一句,这种投射方式是安全的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-17
      • 1970-01-01
      • 2010-10-09
      • 2012-04-15
      • 1970-01-01
      相关资源
      最近更新 更多