Search code examples
iosobjective-ccore-datansmanagedobjectcontext

Can I re-use the context in a block of performBlock?


In general, we will have child/parent context related code like this

dispatch_async(dispatch_get_main_queue(), ^{
    NSManagedObjectContext *childContext = [[[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType] autorelease];
    childContext.parentContext = self.managedObjectContext;
    [childContext performBlock:^{
        // do something with childContext and save
    }];
});

now I need to send network request with AFHTTPRequestOperationManager in performBlock,

dispatch_async(dispatch_get_main_queue(), ^{
    NSManagedObjectContext *childContext = [[[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType] autorelease];
    childContext.parentContext = self.managedObjectContext;
    [childContext performBlock:^{
        [RequestOperationManager POST... parameters... success...{
            // Can I re-use childContext here?
        }];
    }];
});

so can I re-use the context in a block of performBlock?


Solution

  • Yes, you can reuse the childContext instance in the completion block nested within the performBlock block. It will be retained by the block until the block is deallocated.

    However you would likely need to use a further nested block because you'd have to again use performBlock to dispatch the MOC work to the correct queue for childContext because the success block could be dispatched to a different queue. That indicates you may want to nest the childContext performBlock invocation within the success completion block, the opposite nesting from what you've illustrated. But if there's MOC work you plan to do both before and after that POST function, you'll end up with another nested block. It really depends on what real code you wrap around the psuedocode here.

    The options I'm discussing, illustrated.

    childContext.parentContext = self.managedObjectContext;
    [childContext performBlock:^{
        ... update a NSManagedObject...
        [RequestOperationManager POST... parameters... success...{
            [childContext performBlock:^{
                ... update a NSManagedObject...
                ... (and maybe save)
            }];
        }];
    }];
    

    versus

    childContext.parentContext = self.managedObjectContext;
    [RequestOperationManager POST... parameters... success...{         
        [childContext performBlock:^{
            ... update a NSManagedObject...
            ... (and maybe save)
        }];
    }];
    

    You can use the latter if you're not mutating anything in the childContext before calling that POST method with the success completion block.