Advertise here




Advertise here

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Sign In with Google Sign In with OpenID
Please do not post the same thing multiple times. The board software automatically flags certain posts as needing moderator attention. This happens the most often for new users. I'm pretty sure this is made clear at the time you attempt to post. Posting the same thing over and over again just makes that many more posts the moderators have to weed through later. This makes us sad. Don't make us sad. If your post/thread doesn't appear, just wait a while. Don't post it again. If it hasn't shown up by the next day, then you can try again. I normally go through posts in the mornings, and try to check a few times throughout the day, but I'm not here 24/7. There will typically be a significant delay before posts are approved. Just be patient.

NSFetchedResultsController / CoreData with multiple threads

iThomsiThoms Posts: 2New Users
edited May 2012 in iPhone SDK Development
Hi!

I'm currently developping an application which uses CoreData and a NSFectchedResultsController. This application only contains one UITableView which uses a NSFetchedResultsController.

1/ When the application is launched, another thread is detached. In this new thread, a WS call permits to retrieve data from a web server. After the WS call, I store data in my CoreData DB with another NSManagedObjectContext (Apple's best practice: Another thread => Another context). I have to delete all objects of this entity before saving new objects. I merge this other context with the main context via mergeChangesFromContextDidSaveNotification.


// Data Manager (in another thread)
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(contextDidSave:)
name:NSManagedObjectContextDidSaveNotification
object:context];
[context setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];
[context setPersistentStoreCoordinator:[self getPersistentStoreCoordinator]];

...

for (NSManagedObject * obj in objects)
{
[context deleteObject:obj];
}

...

for(NSDictionary *serverObj in serverObjects)
{
objAd = [NSEntityDescription
insertNewObjectForEntityForName:@\"MyEntity\"
inManagedObjectContext:context];
...
}

[context save:&error];

[[NSNotificationCenter defaultCenter] removeObserver:self name:NSManagedObjectContextDidSaveNotification object:context];
[context release];

...

- (void)contextDidSave:(NSNotification *)notification
{

SEL selector = @selector(mergeChangesFromContextDidSaveNotification:);
[[self getContext] performSelectorOnMainThread:selector withObject:notification waitUntilDone:YES];
}

- (NSManagedObjectContext *) getContext
{
return [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
}

- (NSPersistentStoreCoordinator *) getPersistentStoreCoordinator
{
return [(AppDelegate *)[[UIApplication sharedApplication] delegate] persistentStoreCoordinator];
}


2/ Here is my NSFectchedResultsController's getter:


// UIView
- (NSFetchedResultsController*) offersFRC {

if (offersFRC == nil)
{
NSManagedObjectContext *l_ManagedObjectContext = [[DataManager sharedDataManager] getContext];

NSFetchRequest *l_FetchRequest = [[NSFetchRequest alloc] init];

NSEntityDescription *l_Entity = [NSEntityDescription entityForName:@\"MyEntity\" inManagedObjectContext:l_ManagedObjectContext];
[l_FetchRequest setEntity:l_Entity];

[l_FetchRequest setFetchBatchSize:5];

NSNumber *sortType = [self.searchCriterions objectForKey:@\"sortType\"];
NSSortDescriptor *l_SortDescriptor = [[NSSortDescriptor alloc] initWithKey:[Constants getFieldNameBySortType:sortType] ascending:[Constants isAscendingBySortType:sortType]];
[l_FetchRequest setSortDescriptors:[NSArray arrayWithObjects:l_SortDescriptor, nil]];
[l_SortDescriptor release];

NSFetchedResultsController *l_FetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:l_FetchRequest managedObjectContext:l_ManagedObjectContext
sectionNameKeyPath:nil
cacheName:nil];
[l_FetchRequest release];

[self setOffersFRC:l_FetchedResultsController];
[l_FetchedResultsController release],l_FetchedResultsController = nil;

[self.offersFRC setDelegate:self];
}

return offersFRC;
}


3/ I've got the following error when the application is launched:


2012-02-29 11:56:09.119 Nanopost[1996:207] *** Terminating app due to uncaught exception 'NSObjectInaccessibleException', reason: 'CoreData could not fulfill a fault for '0x5c3c760 <x-coredata://E176B0A1-275B-4332-9231-49FD88238C2B/Ads/p231>''
*** Call stack at first throw:
(
0 CoreFoundation 0x02bfe919 __exceptionPreprocess + 185
1 libobjc.A.dylib 0x02e595de objc_exception_throw + 47
2 CoreData 0x028b833f _PFFaultHandlerLookupRow + 1407
3 CoreData 0x028b5ee3 _PF_FulfillDeferredFault + 499
4 CoreData 0x028b9f3f _sharedIMPL_pvfk_core + 95
5 CoreData 0x0292a010 _PF_Handler_Public_GetProperty + 160
6 Foundation 0x02442c4f -[NSSortDescriptor compareObject:toObject:] + 128
7 CoreData 0x0297db5e +[NSFetchedResultsController(PrivateMethods) _insertIndexForObject:inArray:lowIdx:highIdx:sortDescriptors:] + 286
8 CoreData 0x0297e1b2 -[NSFetchedResultsController(PrivateMethods) _postprocessInsertedObjects:] + 402
9 CoreData 0x029841bc -[NSFetchedResultsController(PrivateMethods) _managedObjectContextDidChange:] + 1804
10 Foundation 0x02380c1d _nsnote_callback + 145
11 CoreFoundation 0x02bd6cf9 __CFXNotificationPost_old + 745
12 CoreFoundation 0x02b5611a _CFXNotificationPostNotification + 186
13 Foundation 0x023767c2 -[NSNotificationCenter postNotificationName:object:userInfo:] + 134
14 CoreData 0x028c0519 -[NSManagedObjectContext(_NSInternalNotificationHandling) _postObjectsDidChangeNotificationWithUserInfo:] + 89
15 CoreData 0x028f802b -[NSManagedObjectContext mergeChangesFromContextDidSaveNotification:] + 1579
16 Foundation 0x02395e9a __NSThreadPerformPerform + 251
17 CoreFoundation 0x02bdfd7f __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15
18 CoreFoundation 0x02b3e2cb __CFRunLoopDoSources0 + 571
19 CoreFoundation 0x02b3d7c6 __CFRunLoopRun + 470
20 CoreFoundation 0x02b3d280 CFRunLoopRunSpecific + 208
21 CoreFoundation 0x02b3d1a1 CFRunLoopRunInMode + 97
22 GraphicsServices 0x031e62c8 GSEventRunModal + 217
23 GraphicsServices 0x031e638d GSEventRun + 115
24 UIKit 0x0063cb58 UIApplicationMain + 1160
25 Nanopost 0x0000230a main + 170
26 Nanopost 0x00002255 start + 53
)
terminate called after throwing an instance of '_NSCoreDataException'


Important Notes:

- It crashes only on iOS4
- controllerWillChangeContent is the last function called in my code before application's crash. controllerDidChangeContent / didChangeObject/ didChangeSection are not called.
- When I comment [l_FetchRequest setFetchBatchSize:5] => No more crashes
- When I add a [context save:&error] after objects deletion and before new objects insertion => No more crashes
- When I use [l_FetchRequest setFetchBatchSize:24] => Crashes
- When I use [l_FetchRequest setFetchBatchSize:25] => No more crashes

I have spent a lot of time trying to understand this issue so Thank you very much in advance for your answers! :)

Thomas
Sign In or Register to comment.