简体   繁体   中英

Where to create a NSManagedObjectContext for an NSInvocationOperation

I have multiple NSInvocationOperations created and added to an NSOperationQueue. Two of these NSInvocationOperations create lots of objects of the same parent class (Country and City which subclass Location). It has mostly gone well except that I've noticed changes to one model or the other are kinda clobbered.

Looking at the store (using a sqlite program) I see the first City (of maybe 200 total) created and then all of the Countries (again maybe 200) created. If I delete the app and run it again I'll see the first Country and then all of the Cities.

I hit the docs and noticed that Apple suggestions setting up your per thread MOCs in the start method of you NSOperation. However I'm not using an NSOperation, I'm using an NSInvocationOperation. It's actually making me question more so why they suggest creating your MOC in start.

This is my selector for my NSInvocationOperation...

+ (void)load:(NSString *)file
{
    NSManagedObjectContext *managedObjectContext = [(OSSMAppDelegate *)[[UIApplication sharedApplication] delegate] adHocManagedObjectContext];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(mergeChanges:)
                                             name:NSManagedObjectContextDidSaveNotification
                                           object:managedObjectContext];

    SBJsonParser *jsonParser = [[SBJsonParser alloc] init];

    NSString *json = [[NSString alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:file ofType:@"json"]];

    NSArray *objects = [[jsonParser objectWithString:json] valueForKeyPath:@"objects"];

    for(NSDictionary *object in objects)
    {
        [self createObjectWithObject:object inManagedObjectContext:managedObjectContext];
    }

    NSError *error = nil;
    [managedObjectContext save:&error];

}

...from the app delegate...

- (NSManagedObjectContext *)adHocManagedObjectContext
{
    NSManagedObjectContext *adHocManagedObjectContext = nil;

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];

    if (coordinator != nil)
    {
        adHocManagedObjectContext = [[NSManagedObjectContext alloc] init];
        [adHocManagedObjectContext setPersistentStoreCoordinator:coordinator];
        [adHocManagedObjectContext setUndoManager:nil];
    }

    return adHocManagedObjectContext;
}

...then somewhere else (Note: firstRun calls load:)...

NSInvocationOperation *countryInvocationOperation = [[NSInvocationOperation alloc] initWithTarget:[Country class] selector:@selector(firstRun) object:nil];
[operationQueue addOperation:countryInvocationOperation];

Is there any problem with creating the MOC in the selector that's being invoked? I'd image it has to be since the MOC is tied to the thread it's created on. I guess any pointers as to where I'm going wrong is helpful.

I'm not sure I understand your problem (Do you have missing countries or cities?, do you have incorrect order? give an example of 'clobbered').

As for your question:

Is there any problem with creating the MOC in the selector that's being invoked?

No, there is no problem. the documentation only say it must be created ON the thread you intend to use it ( start and main are methods that will run on the operation thread). hence, NSInvocationOperation will run your method in the operation thread, and you can create your MOC there without worries.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM