【问题标题】:Keep track of index in fast enumeration在快速枚举中跟踪索引
【发布时间】:2011-12-28 03:32:46
【问题描述】:

我想在使用快速枚举的时候得到当前对象的索引,即

for (MyClass *entry in savedArray) {
// What is the index of |entry| in |savedArray|?
}

【问题讨论】:

    标签: objective-c cocoa-touch fast-enumeration


    【解决方案1】:

    查看NSArray 的API,您将看到方法

    - (void)enumerateObjectsUsingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop))block
    

    那就试一试吧

    [savedArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    
        //... Do your usual stuff here
    
        obj  // This is the current object
        idx  // This is the index of the current object
        stop // Set this to true if you want to stop
    
    }];
    

    【讨论】:

    • 添加 - 通过调用*stop = YES 使用停止标志(只是stop = YES 不起作用)
    【解决方案2】:

    我想最直接的解决方案是手动增加索引。

    NSUInteger indexInSavedArray = 0;
    for (MyClass *entry in savedArray) {
       indexInSavedArray++;
     }
    

    或者,您不能使用快速枚举。

        for (NSUInteger indexInSavedArray = 0; indexInSavedArray < savedArray.count; indexInSavedArray++) {
           [savedArray objectAtIndex:indexInSavedArray];
         }
    

    【讨论】:

    • 他也可以用[savedArray indexOfObject:entry];:)
    • 是的,这会起作用,尽管它会非常低效,因为它必须将 isEqual 发送到导致匹配对象的每个对象。例如,需要发送 500 条 isEqual 消息(以及计算对象是否在 isEqual 中实际执行某些操作)才能获得第 500 个元素的索引,然后再发送 501 条消息以获取下一个对象。编辑:也许你在讽刺我错过了一个笑话:)
    【解决方案3】:

    这个问题已经回答了,但我想我会补充一点,计算迭代实际上是 iOS 开发者库文档中提到的技术:

    NSArray *array = <#Get an array#>;
    NSUInteger index = 0;
    
    for (id element in array) {
        NSLog(@"Element at index %u is: %@", index, element);
        index++;
    }
    

    我确信会有一个花哨的把戏,但我想不会。 :)

    【讨论】:

    • Apple 的方式是不安全的,恕我直言,应该避免 - 当有人无辜地在您的代码中添加“中断”或“继续”时,它会出现可怕的错误。遗憾的是,他们的快速枚举设计并不是很好。
    • 如果“break”或“continue”被放置在快速枚举代码中,您的意思是否会出现问题? Apple 是否做了与 C# 不同的事情?只是要求我自己接受教育(并避免未来的错误)。谢谢!
    • 简单示例:示例代码长 2 行。如果它有 20 行长,并且在第 5 行,有人添加了“继续”怎么办? continue 将导致“元素”前进 - 但不是“索引”。啊哈!因此,您将 index++ 放在开头,就在使用它的位置之后。但是,如果有人随后试图在循环体中引用它怎么办?现在它太大了 1. ... 等等
    • @Adam 虽然我同意你的观点,即快速枚举的设计不是很好,但你不能只使用NSUInteger index=-1;,然后在开始时增加索引吗?
    • @jimmery 是的,那很好。除了它看起来是错误的——你正在创建一个不正确的值的索引,而且我已经看到很多复制/粘贴代码或重构代码的情况,其中“-1”的重要性丢失了。基本上:当你需要计数器时不要使用快速枚举(这很危险,它只为你节省了一行代码)
    【解决方案4】:

    如果您想访问索引或返回外部块,这里有一段代码很有用。 (考虑到数组是一个 NSString 的数组)。

    - (NSInteger) findElemenent:(NSString *)key inArray:(NSArray *)array
    {
        __block NSInteger index = -1;
        [array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
            if ([obj isEqualToString:key]) {
                *stop = YES;
                index = idx;
            }
        }];
        return index;
    }
    

    【讨论】:

      【解决方案5】:

      一个简单的观察:如果将索引初始化为 -1,然后将 ++index 作为 for 循环中的第一行,那是否涵盖了所有基础(前提是有人没有在增量)?

      【讨论】:

      • “只要有人没有在增量前面滑代码”最好的基于信仰的编码
      猜你喜欢
      • 2015-12-10
      • 1970-01-01
      • 1970-01-01
      • 2020-05-19
      • 2013-04-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多