Mayank Palotra
Mayank Palotra

Reputation: 127

Crash on [context executeFetchRequest:request error:&error] always in Core Data?

I run my app so always crash on [context executeFetchRequest:request error:&error] because multiple asynchronous data save in core data. So how to handle this problem? I am trying this code.

        NSManagedObjectContext *context =[appDelegate managedObjectContext];
        NSFetchRequest *request = [[NSFetchRequest alloc] init];
        NSEntityDescription *entity = [NSEntityDescription entityForName:@"Client" inManagedObjectContext:context];
        NSPredicate *predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:@"clientId = %@",clientId]];
        [request setPredicate:predicate];
        [request setEntity:entity];

        NSError *error = nil;
        NSMutableArray *mutableFetchResults =(NSMutableArray *)[context executeFetchRequest:request error:&error];
        if (mutableFetchResults == nil)
        {
            NSLog(@"ERROR - %@", error);
        }
        if (mutableFetchResults!=nil && [mutableFetchResults count]>0)
        {
            return [mutableFetchResults objectAtIndex:0];
        }
        else
        {
            return nil;
        }

This is my crash log:

Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSCFSet: 0x7fac74d0a290> was mutated while being enumerated.'
*** First throw call stack:
(
    0   CoreFoundation                      0x000000010baa3e65 __exceptionPreprocess + 165
    1   libobjc.A.dylib                     0x000000010b0c8deb objc_exception_throw + 48
    2   CoreFoundation                      0x000000010baa37c4 __NSFastEnumerationMutationHandler + 132
    3   CoreData                            0x0000000109f486ef -[NSManagedObjectContext executeFetchRequest:error:] + 2111
    4   CuztomisePharma                     0x0000000109acbec9 -[SyncManager getClientByClientId:] + 489
    5   CuztomisePharma                     0x0000000109ac9cf6 -[SyncManager saveClient:] + 214
    6   CuztomisePharma                     0x0000000109ac98a6 -[SyncManager firstTimeSync] + 2406
    7   CuztomisePharma                     0x0000000109a31029 -[LoginViewController loginServerCall] + 1273
    8   Foundation                          0x000000010ad52dfb __NSThread__start__ + 1198
    9   libsystem_pthread.dylib             0x000000010e37299d _pthread_body + 131
    10  libsystem_pthread.dylib             0x000000010e37291a _pthread_body + 0
    11  libsystem_pthread.dylib             0x000000010e370351 thread_start + 13
)
2016-05-25 14:23:08.682 CuztomisePharma[6615:146656] The selected car is: (
    "<Drug: 0x7fac75d18150> (entity: Drug; id: 0xd0000000002c001e <x-coredata://AE430EFF-FF79-48C9-BDB3-08707B8B172F/Drug/p11> ; data: <fault>)"
)
libc++abi.dylib: terminating with uncaught exception of type NSException

Upvotes: 0

Views: 2911

Answers (3)

Marcus S. Zarra
Marcus S. Zarra

Reputation: 46718

-executeFetchRequest: does NOT return a mutable array. Just because you cast it to a NSMutableArray does not make it a NSMutableArray.

First, you should not be doing a mutable array as you are not mutating it.

Second, you should not be casting the return. If you want a mutable array you need to convert it properly:

NSMutableArray *mutableFetchResults = [[context executeFetchRequest:request error:&error] mutableCopy];

Again, there is never a reason to use a mutable array on a fetch result. The results array is not mutable.

The error you showed in your question does not match the code you showed as that code is not mutating the array.

Show the code for -getClientByClientId: as that is where your crash is occurring.

Upvotes: 0

PiyushRathi
PiyushRathi

Reputation: 959

Are you doing two operations simultaneously? One enumerate it and the other going to save.

Upvotes: 1

Surya Subenthiran
Surya Subenthiran

Reputation: 2217

NSManagedObjectContext is not thread safe. If you creating context on main thread, then you can access the context only on the main thread.

So you have to run the executeFetchRequest in the main thread, instead you can use performBlock which will schedule it to run on its own thread.

[context performBlock:^{
    NSMutableArray *mutableFetchResults =(NSMutableArray *)[context executeFetchRequest:request error:&error];

}];

Note: performBlock won't work if you're initialising the context in the older NSConfinementConcurrencyType confinement model.

Hope this helps.

Upvotes: 1

Related Questions