0

Hi in one of my application. I am using queues to download a file from server and after file download completes I am updating the status in coredata (Sync type).While Update status in core data db app is crashing continously.

Here is the code which I used in my app

 **In Download file method**

    NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadfileinThread:) object:params] ;

    [operation addObserver:self forKeyPath:@"isFinished" options:0 context:nil];

    [downloadQueue addOperation:operation] ;


    **In Download file in Thread. (Here actual file will download)**

    -(void) downloadfileinThread: 

    {

    [self UpdateDatabase:file with:updatesArray1] ; //updatesArray1 contains dictionaries (Syncstatus:0 like this)

    }

    **DB updation**

    -(void) UpdateDatabase:(id)_object with:(NSMutableArray *)updatesArray
    {

    NSManagedObjectContext *threadManagedObjectContext = [self myManagedContext] ;

[[NSNotificationCenter defaultCenter] removeObserver:self name:NSManagedObjectContextObjectsDidChangeNotification object:threadManagedObjectContext] ;

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mergeContextChangesForNotification:) name:NSManagedObjectContextObjectsDidChangeNotification object:threadManagedObjectContext];

  NSManagedObject *object = [threadManagedObjectContext objectWithID:[_object objectID]] ;

            if (updatesArray)

            {
            for (NSDictionary *updatedDic in updatesArray)

            {

         [object setValue:[[updatedDic allValues]lastObject] forKey:[[keyValue allKeys]lastObject]];

             }

             NSError *error;
             bool result = [threadManagedObjectContext save:&error];
                 if (!result)
                 {
                     NSLog(@" error saving context, %@, %@", error, error.userInfo);
                 }
            }
    }        

Crash Message: Terminating app due to uncaught exception 'NSGenericException', reason: '* Collection <__NSDictionaryM: 0xd01b9e0> was mutated while being enumerated.'

Please help me in resolving this issue.

rptwsthi
  • 10,094
  • 10
  • 68
  • 109
user3341324
  • 45
  • 1
  • 9
  • What is `keyValue`? That is neither declared nor initialized in your question. It would also be helpful to include the stack trace in your question, not just the text of the exception. As is, your notification handler has several crashing bugs that are unrelated to the exception. – quellish Sep 07 '14 at 05:42
  • HI Quelish KeyValue is SyncStaus:0 – user3341324 Sep 07 '14 at 05:49
  • Does that mean it's the string "SyncStatus:0"? – quellish Sep 07 '14 at 05:50
  • Hi in my updatesArray1 I have a dictionaries. Each dic contains one key value pair that is key is SyncStatus and value is 0. – user3341324 Sep 07 '14 at 05:51
  • Hi Quelish actual problem this one http://www.pixeldock.com/blog/collection-was-mutated-while-being-enumerated-during-coredata-operation-on-background-thread/ – user3341324 Sep 07 '14 at 05:52
  • No, from what you posted in your question it's definitely not what's described at that link. He's describing a problem with Core Data thread confinement, your exception is not a Core Data problem but a design problem. – quellish Sep 07 '14 at 05:58
  • Here Also I am updating NSManagedObject and while set the value for that app is crashing. – user3341324 Sep 07 '14 at 06:03
  • Core Data has nothing to do with the exception that is reported in your question. You have other Core Data issues in the code you posted, but your question is about the crash and exception you are seeing - which from what you have posted has nothing to do with Core Data, any everything to do with object mutability. – quellish Sep 07 '14 at 06:05

2 Answers2

0

I am not sure what issue are you facing here, as I can't find anything obvious in your code, but generally this problem occurs, when a mutable object(array or dictionary), get updated(add/remove object) in side a loop where it's been read. Try avoiding any such activity in your code.

Another suggestion will be. Add Exception break point in your code. And run your code with break point on. This will indicate you to exact line you are facing this exception. And attach code with that line, for further clearing.

Community
  • 1
  • 1
rptwsthi
  • 10,094
  • 10
  • 68
  • 109
0

The exception you are getting:

* Collection <__NSDictionaryM: 0xd01b9e0> was mutated while being enumerated.

Indicates an NSMutableDictionary instance was changed while it was being enumerated. the M in __NSDictionaryM indicates it's a mutable dictionary. Out of the code you included in your answer, a dictionary is being enumerated in one place that I can see:

[object setValue:[[updatedDic allValues]lastObject] forKey:[[keyValue allKeys]lastObject]];

When [updatedDic allValues] is called Foundation uses Fast Enumeration to compose the array of values. While Foundation is doing this, the dictionary object is being changed (mutated) elsewhere in your application. It's likely that whatever part of your program calls this method built an NSMutableArray of NSMutableDictionarys, called this method, and then continued to modify those NSMutableDictionarys. This is what is causing your problem. Do not change collections while they are being enumerated. A very simple fix would be to add immutable copies of the NSMutableDictionarys to the mutable array:

[someArray addObject:[someDictionary copy]];

It's entirely possible though that the exception is actually happening elsewhere, without the stack trace it's impossible to tell.

quellish
  • 21,123
  • 4
  • 76
  • 83