Search code examples
iosiphoneobjective-ccore-datarestkit-0.20

Core Data objects become null


I am creating a tasks application which should support offline mode. I have used RestKit to download tasks and mapped that in local Core data.

This is working good in online mode. But in offline there is strange problem. I use NSPredicate to fetch data from local storage. For this I am using Magical Records.

+ (void)getIdeasTasksWithPageNo:(int)pageNo completionHandler:(void (^)(NSArray *, NSError *))completionHandler {

    NSArray *tasks = [self MR_findAllWithPredicate:[NSPredicate predicateWithFormat:@"due_date = nil AND user_id = %@", [DBUsers currentUser].id]];
    completionHandler(tasks, nil);
}

And I call it like this:

[DBTasks getIdeasTasksWithPageNo:1 completionHandler:^(NSArray *tasks, NSError *error) {
            if (!error) {
                [self displayTasksWithResults:tasks forPageNo:1];                   

            } else {
                NSLog(@"Error is %@", error);
            }
        }];

And this is how I am displaying it in UITableView

-(void)displayTasksWithResults:(NSArray *)tasks forPageNo:(int)pageNo {
    if (!self.tasksArray) {
        self.tasksArray = [[NSMutableArray alloc] init];

    } else {
        [self.tasksArray removeAllObjects];
    }
    [self.tasksArray addObjectsFromArray:tasks];
    [self.tableview reloadData];
}

This is working only for first time and all tasks are populated in UITableView.

Problem is after the UITableView is populated, all records in self.tasksArray become Null. If I scroll UITableView, the table rows start being empty.

But if I print self.tasksArray in displayTasksWithResults method, it prints perfectly.

(
    "Title: Task 01",
    "Title: You've gone incognito. Pages you view in incognito tabs won't stick around in your browser's history, cookie store, or search history after you've closed all of your incognito tabs. Any files you download or bookmarks you create will be kept. ",
    "Title: Task 06",
    "Title: Task 04",
    "Title: Hi",
    "Title: Task 3",
    "Title: Task 4",
    "Title: Hi 4",
    "Title: hh",
    "Title: Task 02",
    "Title: Task 05\n",
    "Title: Task 4",
    "Title: Task 5",
    "Title: Task 2 updated",
    "Title: Here is a task. ",
    "Title: Task 03",
    "Title: Hi 3",
    "Title: Task 2",
    "Title: Hi 2",
    "Title: Testing task email with Idea Task",
    "Title: Task f6",
    "Title: 1.117",
    "Title: Task f5",
    "Title: Task f12",
    "Title: Task f4",
    "Title: Task f3",
    "Title: 111.0.113",
    "Title: 111.0.115",
    "Title: Pages you view in incognito tabs won't stick around in your browser's history, cookie store, or search history after you've closed all of your incognito tabs. Any files you download or bookmarks you create will be kept.",
    "Title: Task f7",
    "Title: 1.116",
    "Title: 1.118",
    "Title: Going incognito doesn't hide your browsing from your employer, your internet service provider, or the websites you visit. ",
    "Title: 111.0.111"
)

If I print self.taskArray later, may be in didSelectRow delegate of UITableView, it prints like below:

(
    "Title: (null)",
    "Title: (null)",
    "Title: (null)",
    "Title: (null)",
    "Title: (null)",
    "Title: (null)",
    "Title: (null)",
    "Title: (null)",
    "Title: (null)",
    "Title: (null)",
    "Title: (null)",
    "Title: (null)",
    "Title: (null)",
    "Title: (null)",
    "Title: (null)",
    "Title: (null)",
    "Title: (null)",
    "Title: (null)",
    "Title: (null)",
    "Title: (null)",
    "Title: (null)",
    "Title: (null)",
    "Title: (null)",
    "Title: (null)",
    "Title: (null)",
    "Title: (null)",
    "Title: (null)",
    "Title: (null)",
    "Title: (null)",
    "Title: (null)",
    "Title: (null)",
    "Title: (null)",
    "Title: (null)",
    "Title: (null)"
)

I think this may be some thing related to NSManagedObjectContext, but don't know how to fix it.

Please help!


Solution

  • The problem is that (as I wrote in a comment) that the objects are fetched on a background thread, but used on the main (UI) thread. Managed objects can only "live" in the context that they were created in. If the context is deallocated, the objects still exist, but the property accessor methods return just nil.

    Possible solutions:

    • Fetch the objects on the main thread.
    • Use

      NSManagedObject *copy = [[mainContext objectWithID:[object objectID]];
      

      to "copy" the objects from the background context to the main context. (Perhaps MagicalRecord has a convenience method.)

    • Instead of fetching managed objects, set

      [fetchRequest setResultType:NSDictionaryResultType];
      [fetchRequest setPropertiesToFetch:@[@"title", ...]];
      

      to fetch an array of dictionaries with the attributes you are interested in.