ioscore-datagrand-central-dispatchnsmanagedobjectnsmanagedobjectid

Cannot add Managed Object ID to NSMutableArray in GCD with Child Managed Object Child Context


I'm using GCD as well as Core Data. I'm aware Core Data is not thread safe, so I create child Managed Object Context (tempContext) with the mainContext as the parent. MainContext has a PCS to save data. What I'm doing is:

  1. Pull posts from Facebook
  2. Save each post to Core Data by creating a new Managed Object called Post, updating it and saving it
  3. while I process each post, if it needs additional handling, I add the post.obectID to an NSMutableArray of Managed Object IDS. This NSMutableArray is used by another process to finish updating the posts. I am using object IDs because the separate process will not be in the same tempContext, thus I will fetch the Post from Core Data using the object ID.

The process gets data, and I see it is stored within store.data (I use the product called Base to view the physical database file's content). But, I cannot seem to store the post's Object ID. As you see in code, I am using NSLog to print out the post's object ID, and I see them, thus I know the object IDs are there. Code also shows I am doing [tempContext save] and I am doing [mainContext save:], thus I should now have permanent, not temporary object IDs for posts. Again, the data is within Core data's physical file, but the mutable array count is still = 0.

What am I doing wrong to save the object IDs to NSMutableArray? In code you will see commented out where I've tried running the [mutableArray addObject:p.objectID] even on the main Queue, but it does not matter.

Here is my code:

- (void)processPosts {

NSLog(@"-- Begin processPosts --");

dispatch_async(_processPostsQ, ^{

    for (NSDictionary * info in _posts)
    {
        NSManagedObjectContext * tempContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
        tempContext.parentContext = mainMOContext;

        // If Post exists, rewrite over top of it. otherwise create a new one
        NSFetchRequest      * fetchRequest = [[NSFetchRequest alloc] init];
        NSEntityDescription * entity       = [[mainMOModel entitiesByName] objectForKey:@"Post"];

        [fetchRequest setEntity:entity];

        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"fb_post_id = %@",
                                  [info objectForKey:@"post_id"]];

        [fetchRequest setPredicate:predicate];

        NSSortDescriptor *sd = [NSSortDescriptor sortDescriptorWithKey:@"fb_post_id" ascending:YES];
        [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sd]];

        NSError * error = nil;
        NSArray * fetchResults = [tempContext executeFetchRequest:fetchRequest error:&error];

        Post * p = [NSEntityDescription insertNewObjectForEntityForName:@"Post" inManagedObjectContext:tempContext];

        if (fetchResults.count > 0)
        {
            p = [fetchResults objectAtIndex:0];
        }

        NSDictionary * appData = [[NSDictionary alloc]init];
        appData = [info objectForKey:@"app_data"];

        p.fb_actor_id       = [info objectForKey:@"actor_id"];
        p.fb_app_data       = [self archivedData:[info objectForKey:@"app_data"]];
        p.fb_attachment     = [self archivedData:[info objectForKey:@"attachment"]];
        p.fb_created_time   = [info objectForKey:@"created_time"];
        p.timestamp         = [info objectForKey:@"updated_time"];
        p.fb_attribution    = NULL_TO_NIL([info objectForKey:@"attribution"]);
        p.fb_message        = NULL_TO_NIL([info objectForKey:@"message"]);
        p.fb_type           = NULL_TO_NIL([info objectForKey:@"type"]);
        p.fb_post_id        = [info objectForKey:@"post_id"];
        p.fb_likes_info     = [self archivedData:[info objectForKey:@"like_info"]];
        p.fb_comments_info  = [self archivedData:[info objectForKey:@"comment_info"]];
        p.fb_parent_post_id = NULL_TO_NIL([info objectForKey:@"parent_post_id"]);
        p.fb_permalink      = NULL_TO_NIL([info objectForKey:@"permalink"]);
        p.fb_photo_data     = nil;
        p.fb_place          = NULL_TO_NIL([info objectForKey:@"places"]);
        p.fb_source_id      = [info objectForKey:@"source_id"];
        p.social_network    = @"facebook";
        p.fkPostToFriend    = [[FriendStore sharedStore]findFriendWithFBUID:[info objectForKey:@"source_id"] withMOContext:tempContext];

        [tempContext save:&error];

        dispatch_async(dispatch_get_main_queue(), ^{
            NSError * error;
            [mainMOContext save:&error];
        });


        if (appData.count > 0)
        {
            if ([[appData objectForKey:@"photo_ids"] count] > 0)
            {
                NSLog(@"   -- photos need to be loaded for postID: %@",p.objectID);
                //dispatch_async(dispatch_get_main_queue(), ^{
                    [_postsNeedingPhotos addObject:p.objectID];
                //});
            }
        }
    }

    NSLog(@"ProcessPosts: num of posts needing photos: %d",_postsNeedingPhotos.count);
    dispatch_async(_getPhotosQ, ^{
        [self loadPhotoData];
    });
    NSLog(@"-- End processPosts --");
});

}

Thanks in advance for your help!


Solution

  • I'm an idiot. I forgot to initialize _postsNeedingPhotos with:

    _postsNeedingPhotos = [[NSMutableArray alloc] init];

    Now everything runs fine... :)