-->

NSMutableArray replace object

2020-07-24 05:53发布

问题:

I try to find object in my array and if success I need to replace object from my array to new object

 for (id existingSig in allSignature)
   if ([[existingSig objectForKey:@"SignatureName"] isEqualToString:[item objectForKey:@"name"]])
    {    
      [allSignature removeObject:existingSig];
      [allSignature addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"1", @"SignatureIsRich", [item objectForKey:@"name"], @"SignatureName", generatedID, @"SignatureUniqueId", nil]];
     }

I have error 'NSCFArray: 0x100551f10> was mutated while being enumerated'

回答1:

As others have said, you cannot mutate a MutableArray while it is being Enumerated. You could handle it by having two arrays of what to remove and what to add after the loop.

NSMutableArray *remove = [NSMutableArray array];
NSMutableArray *add = [NSMutableArray array];
for (id existingSig in allSignature){
   if ([[existingSig objectForKey:@"SignatureName"] isEqualToString:[item objectForKey:@"name"]])
    {    
      // Add to the array of objects to be removed
      [remove addObject:existingSig];
      // Add to the array of objects to be added
      [add addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"1", @"SignatureIsRich", [item objectForKey:@"name"], @"SignatureName", generatedID, @"SignatureUniqueId", nil]];
     }
}
[allSignature removeObjectsInArray:remove]; // Remove objects
[allSignature addObjectsFromArray:add]; // Add new objects


回答2:

The easiest way is to make a copy and iterate over that, then modify the original.



回答3:

I have a map array method I have in a NSArray Category for this very purpose

- (NSArray *) cw_mapArray:(id (^)(id obj))block
{
    NSMutableArray * cwArray = [[NSMutableArray alloc] init];
    [self cw_each:^(id obj, NSUInteger index, BOOL *stop) {
        id rObj = block(obj);
        if (rObj) {
            [cwArray addObject:rObj];
        }
    }];
    return cwArray;
}

this way I can get a new array and then just change the array with the new array. You can change cw_each to enumerateObjectsUsingBlock:. Basically this is simple, if you want to map the object to the new array you just return the object as is in the block, otherwise modify it and return that or if you don't want to map the object to the new array then return nil. Its not very much code and works wonderfully.