【问题标题】:Getting exception as "Collection was mutated while being enumerated"获取异常为“集合在被枚举时发生了变异”
【发布时间】:2014-03-31 22:35:20
【问题描述】:

当我使用此代码时,我发现 Collection 在被枚举异常时发生了变异,任何人都可以建议我如何摆脱这种情况。

PaymentTerms * currentElement;
for (currentElement in termsArray)
{
    printf("\n currentElement Value........%s",[currentElement.days UTF8String]);
    printf("\n Str value...%s",[Str UTF8String]);
    NSRange range = [currentElement.days rangeOfString:Str options:NSCaseInsensitiveSearch];
    if(!(range.location != NSNotFound))
    {
        PaymentTerms *pTerm1 = [[PaymentTerms alloc]init];
        pTerm1.days = Str;
        printf("\n  pTerm1.days...%s",[ pTerm1.days UTF8String]);
        [termsArray addObject:pTerm1];
    }   
}

希望我能得到你方的快速响应。 预先感谢, 莫尼什。

【问题讨论】:

    标签: iphone objective-c


    【解决方案1】:

    枚举时不能更改数组。作为一种解决方法,您应该在临时数组中累积新对象并在枚举后添加它们:

    PaymentTerms * currentElement;
    NSMutableArray* tempArray = [NSMutableArray array];
    for (currentElement in termsArray)
    {
        NSRange range = [currentElement.days rangeOfString:Str options:NSCaseInsensitiveSearch];
        if(!(range.location != NSNotFound))
        {
           PaymentTerms *pTerm1 = [[PaymentTerms alloc]init];
           pTerm1.days = Str;
           [tempArray addObject:pTerm1];
           [pTerm1 release];
        }   
    }
    [termsArray addObjectsFromArray: tempArray];
    

    附:不要忘记释放您创建的 pTerm1 对象 - 您的代码包含内存泄漏

    回应发帖者的评论(和实际任务) - 我认为最简单的方法是制作 bool 标志来指示是否在周期中找到了日值。如果不是 - 在循环结束后添加新对象:

    PaymentTerms * currentElement;
    BOOL dayFound = NO;
    for (currentElement in termsArray)
    {
        NSRange range = [currentElement.days rangeOfString:Str options:NSCaseInsensitiveSearch];
        if(range.location != NSNotFound)
            dayFound = YES;
    }
    if (!dayFound)
         // Create and add new object here
    

    【讨论】:

    • 感谢您提供有用的代码。但我又遇到了一个问题。实际上,如果数组不存在,我需要检查字符串,我必须将其添加到数组列表中。现在问题是我的列表中有 3 个项目不等于我正在搜索的字符串,所以它添加了 3 次而不是 1 次。对此还有其他建议吗?
    • 你不需要在这里释放 tempArray 因为你永远不会拥有它。此外,!(range.location != NSNotFound)(range.location == NSNotFound) 相同。
    • @vodkhang,不这样做,如果 termsArray 中的任何对象的 day 属性与 Str 不同,您只需添加一个新元素
    • 算了,该死的。这是一个愚蠢的错误:)。你的新的是正确的
    • 如果他不想在新数组中复制值(例如,当使用大数组以避免浪费内存时)他可以简单地使用标准 for 循环
    【解决方案2】:

    这条线[termsArray addObject:pTerm1]; 将抛出该异常。您不能从 for each 循环内的数组中添加/删除元素。 for (currentElement in termsArray)

    【讨论】:

      【解决方案3】:

      是的...我们无法在数组更新时进行枚举...这可能会让具有 ActionScript 背景的程序员感到恼火。有时情况会变得更糟,例如“您甚至不会在运行时遇到崩溃或提示您在枚举时更新数组计数”-当时的执行行为异常。

      顺便说一句,您可以选择这种类型的实现,您可以对代码进行细微的更改。

       for (int i=0 ; i< termsArray.count ;i++)  //counting termsArray on every iteration
       {
        id currentElement  = [ termsArray objectAtIndex:i];
        ......
        .....
       }
      

      当然,This(i

      【讨论】:

        【解决方案4】:

        您在循环时将一个对象添加到您的集合中,这就是导致错误的原因。您的 if 语句嵌套在 for

        【讨论】:

          【解决方案5】:

          发生错误是因为您在 for 循环中向 termsArray 添加新对象

          • 创建一个新的空数组(例如newTermsArray)
          • 在第一个循环中创建这些新项目并将其添加到 newTermsArray
          • 然后您将需要第二个循环将 newTermsArray 中的项目添加回原来的 termsArray

          【讨论】:

            【解决方案6】:

            刚刚在一个相当复杂的应用程序中处理了相同的错误。解决方案很简单 - 创建一个副本并使用数组的副本(如果需要,可以将其从原始副本中删除。然后丢弃副本。

            for(CharacterModelNode* node in self.allPlayers)
            {
               // Some operation that may mutate allPlayers (ex: player dies from poison damage and is removed from this array at some other part of an app)
            
            }
            
            //workaround in some cases - create a copy of array and run operations that can kill player on this array (it will not be mutated anywhere else in the app
            
            NSArray* allPlayersCopy = [self.allPlayers copy];
            
            for(CharacterModelNode* node in allPlayersCopy)
            {
                [node.character refreshBuffs];
            }
            

            【讨论】:

              【解决方案7】:

              使用 try 和 catch 处理 nsmutable 数组中的异常

              @try {
                  //code for accessing element.
              
                  }
                  @catch (NSException *exception) {
              
              
                     /// show exception here
              
                  }
              

              【讨论】:

              • 这不能回答 OP 的问题。请重新阅读问题并考虑@Vladimir 的回答。
              猜你喜欢
              • 2014-07-04
              • 2014-02-15
              • 2017-11-22
              • 2012-05-11
              • 2013-01-29
              • 1970-01-01
              • 2011-03-27
              • 1970-01-01
              • 2023-03-13
              相关资源
              最近更新 更多