我的应用程序从第三方数据库下载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)
{
}
}];
}
答案 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解决方案。