带有Magical Record的导入记录不会立即显示在tableView中

时间:2014-01-07 14:02:59

标签: ios core-data magicalrecord

我的应用程序从第三方数据库下载XML文件(使用AFNetworking),然后使用NSXMLParser提取我需要的信息,随时随地创建包含子节点的记录。我使用MagicalRecord与CoreData进行通信。下载和解析部分工作正常,但在我完成后,并非所有条目都在我的表格中可见,我猜测当我刷新tableView时MR还没有完成。如果我离开tableView并返回,则会显示所有记录。

我使用dispatch_group确保在所有下载和导入任务完成之前不更新用户界面。使用NSLog我已经确认dispatch_group_notify块中的代码确实在完成所有下载和解析后执行。

有关如何修复代码以便所有记录立即显示在表格中的任何建议吗?

这里有一些代码:

-(void) importRecords
{
    dispatch_group_t dispatchGroup = dispatch_group_create();

for (NSString *s in self.newRecords)
    {
       dispatch_group_enter(dispatchGroup);

       NSData *data = [self downloadDataforRecord: s]; // using AFNetworking
       if (data)
         [self importData: data];

       dispatch_group_leave(dispatchGroup);
     }

     dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^{
     // done with all the downloading and parsing
     // now update the UI

        self.records = [NSMutableArray arrayWithArray: [Record MR_findAllSortedBy: @"id" ascending: ascending]];

        [self.tableView reloadData];
    });
}


- (void) importData:(NSData *) data
{
    [MagicalRecord saveWithBlock: ^(NSManagedObjectContext *localContext) {
        Root *rootObject = [[Root alloc] init];
        rootObject.context = localContext;

        NSXMLParser *parser = [[NSXMLParser alloc] initWithData: data];

        parser.delegate = rootObject;
        [parser setShouldProcessNamespaces: YES];
        [parser parse];

      // during the parse, records and subnodes are created using: 
      // [Record MR_createInContext: context]; 
      // where context is the same as in the rootObject above
       }
                  completion: ^(BOOL success, NSError *error) {
                      if (error)
                      {
                          // show error alert
                      }
                      else if (success)
                      {
                      }
                  }];

}

3 个答案:

答案 0 :(得分:1)

为什么不能按照以下方式使用完成处理程序

completion: ^(BOOL success, NSError *error) {
                  if (error)
                  {
                      // show error alert
                  }
                  else if (success)
                  {
                       self.records = [NSMutableArray arrayWithArray: [Record MR_findAllSortedBy: @"id" ascending: ascending]];
                       [[NSOperationQueue mainQueue] addOperationBlock:^{
                            [self.tableView reloadData];
                       }];
                  }
              }];

并且您不需要实现dispatch_group_t。

答案 1 :(得分:1)

您的主要问题是您在调度块中进行调度。因此,在导入完成之前调用dispatch_group_notify块。如果你仍想使用一个调度组来表示你的导入完成,你需要阻止外部块,通常,我会使用dispatch_semaphore_t来阻止这样:

dispatch_semaphore_t waitForSave = dispatch_semaphore_create(0);
dispatch_group_async(save_group, save_queue, ^{

    //do your import here
    dispatch_semaphore_signal(waitForSave);
});

dispatch_semaphore_wait(waitForSave, DISPATCH_TIME_FOREVER);
// trigger your UI update here.

我建议这种方法的原因是因为你正在使用 [MagicalRecord saveWithBlock:] ,如果查看源代码,则会将该块调度到另一个后台队列。该队列很可能与您使用的队列不同(因为MagicalRecord创建了自己的私人保存队列)。因此,在保存操作实际完成时,您必须等待操作完成并执行UI更新。

答案 2 :(得分:0)

这就是我最终要做的事情。

我在MagicalRecord保存块的成功块中放置了一个计数器,并为每次导入增加它。一旦计数器等于newRecords的数量,我知道最后一个被导入,我可以更新我的UI。

也许不是最有效和最优雅的方式,但现在它可行。也许经过一些阅读后,我想出了一个GCD解决方案。