Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Magical Record background save seems to be blocking UI

I have a NSOperation that I put in a queue. The NSOperation does some long running photo processing then I save the information/meta data in core data for that photo. In the main method of my custom NSOperation class is where I execute the below block of code

-(void)main
{
    //CODE ABOVE HANDLES PHOTO PROCESSING...
    //........

    //THEN I SAVE ALL DATA BELOW LIKE SO
    [MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {

        Post *post = [Post createInContext:localContext];

        //set about 15 pieces of data, all strings and floats
        post.XXXX = XXXXX;
        post.DDDD = DDDDD;
        etc...
    } completion:^(BOOL success, NSError *error) {
        NSLog(@"Done saving");
    }];
}

My issue is that even with only 3 photos when it saves it really freezes my UI. I would have thought executing this in the NSOperation I would be fine.

I should add that each NSOperation processes one photo, so at times the queue could have 5-10 photos, but I would not think this would make any difference, even with just three like I said its freezing the UI.

Thank you for the help.

UPDATE:------------*--------------

I switched to version 2.2 but that seems to be blocking the UI even more...also now I'm using

-(void)main
{
    NSManagedObjectContext *localContext = [NSManagedObjectContext    contextForCurrentThread];
    //CODE BELOW HANDLES PHOTO PROCESSING...
    //........

    //THEN I SAVE ALL DATA BELOW LIKE SO
    Post *post = [Post createInContext:localContext];

    //set about 15 pieces of data, all strings and floats
    post.XXXX = XXXXX;
    post.DDDD = DDDDD;


    [localContext saveToPersistentStoreWithCompletion:^(BOOL success, NSError *error) {

    }];
}

This is all done in my NSOperation class, am I doing something wrong?

like image 299
inks2002 Avatar asked Jun 25 '13 18:06

inks2002


1 Answers

Don't put the saveWithBlock calls in a background thread. You're effectively creating a background thread from a background thread, which, in this case, is just slowing you down. You should just be able to call saveWithBlock and it should put all your saving code in the background. However, I'm also noticed that you make all your changes in the main UI page of the code, and only call save afterward. This is the wrong usage of this method. You want to do something more like this:

[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {
    Post *post = [Post createInContext:localContext];

    //photo processing
    //update post from photo processing
} completion:^(BOOL success, NSError *error) {
   //This is called when data is in the store, and is called on the main thread
}];

If you do need an NSOperation, I suggest a different pattern:

- (void) main {
   NSManagedObjectContext *localContext = [NSManagedObjectContext confinementContext];
  // Do your photo stuff here

  Post *post = [Post createInContext:localContext];
  //more stuff to update post object

  [localContext saveToPersistentStoreAndWait];

}
like image 68
casademora Avatar answered Nov 02 '22 22:11

casademora