在尝试了解有关 Core Data 和多线程的更多信息时,我编写了一个无法保存到 Core Data 的应用程序。首先一些 背景。在我的 View 出现之前,我创建了托管上下文。这发生在 主线程:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if (!self.managedObjectContext) [self useDocument];
}
- (void)useDocument
{
NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
url = [url URLByAppendingPathComponent:MY_DOCUMENT];
UIManagedDocument *document = [[UIManagedDocument alloc] initWithFileURL:url];
if (![[NSFileManager defaultManager] fileExistsAtPath:[url path]]) {
[document saveToURL:url
forSaveOperation:UIDocumentSaveForCreating
completionHandler:^(BOOL success) {
if (success) {
NSLog(@"@@@AMRO--->managedObjectContext has been setup");
self.managedObjectContext = document.managedObjectContext;
[self refresh];
}
}];
} else if (document.documentState == UIDocumentStateClosed) {
[document openWithCompletionHandler:^(BOOL success) {
if (success) {
NSLog(@"@@@AMRO--->managedObjectContext has been opened");
self.managedObjectContext = document.managedObjectContext;
[self refresh];
}
}];
} else {
NSLog(@"@@@AMRO--->managedObjectContext has been set");
self.managedObjectContext = document.managedObjectContext;
}
}
当我的 View 出现时,我使用这种方法从客户端获取数据。这 我这样做的原因是因为我不想作为我的客户阻止我的观点 正在刷新:
dispatch_queue_t fetchQ = dispatch_queue_create("Client Fetch", NULL);
dispatch_async(fetchQ, ^{
[self.managedObjectContext performBlock:^{
dispatch_async(dispatch_get_main_queue(), ^{
[self reload];
dispatch_async(fetchQ, ^{
[self refreshClientInformation];
});
});
}];
});
调用 refreshClientInformation
,需要大约 2 分钟来检索
信息,但是,我希望同时加载 View
有。上述方法阻止了我
尽管明确调用了,但仍能保存到上下文中
[self.managedContext save:&error]
在 refreshClientInformation
每次客户端数据更新后。 refreshPersonalClientInformations
在“Client Fetch”线程队列中执行。
- (void) refreshPersonalClientInformation
{
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"CLIENT"];
request.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"stationId" ascending:YES]];
NSDate *twoHoursAgo = [NSDate dateWithTimeIntervalSinceNow:-2*60*60];
request.predicate = [NSPredicate predicateWithFormat:@"conditionsUpdated < %@", twoHoursAgo];
NSError *error = nil;
int counter = 0;
// Execute the fetch
NSArray *matches = [self.managedObjectContext executeFetchRequest:request error:&error];
// Check what happened in the fetch
if (!matches) { // nil means fetch failed;
NSLog(@"ERROR: Fetch failed to find CLIENT %@ in database", DEFAULT);
} else if (![matches count]) { // none found, so lets retrieve it below
return;
} else {
for (CLIENT *client in matches) {
NSDictionary *clientDict = [ClientFetcher clientInfo:client.clientId];
client.name = [clientDict[NAME] description];
client.age = [clientDict[AGE] description];
client.updated = [NSDate date];
if (![self.managedObjectContext save:&error]) {
NSLog(@"@@@@@@@@@@@@@@@@@@@@@@@@@@AMRO Unresolved error %@, %@", error, [error userInfo]);
}
//Have to rate limit requests at no more than 10 per minute.
NSLog(@"Sleeping for 6s");
sleep(6);
NSLog(@"Done sleeping for 6s");
}
}
}
我什至尝试通过这样做在 refreshPersonalClientInfo 中运行保存:
dispatch_async(dispatch_get_main_queue(), ^{
[self.managedObjectContext save:nil];
});
但这没有用,没有检测到错误
作为实验,当我的 View 出现并且我的
核心数据最终得到保存,问题是我的 View 被阻止了,我必须
在检索数据时等待很长时间。另外,当我说最终时,我的意思是它不会在我调用 [self.managementContext save:nil]
之后发生,而是在几分钟之后:
dispatch_queue_t fetchQ = dispatch_queue_create("Client Fetch", NULL);
dispatch_async(fetchQ, ^{
[self.managedObjectContext performBlock:^{
[self refreshPersonalClientInformation];
dispatch_async(dispatch_get_main_queue(), ^{
[self reload];
});
}];
});
关于我应该如何在后台线程中检索我的信息的任何建议 并能够在我仍然可以访问我的 UI 的同时将数据保存到磁盘?
最佳答案
您最好创建一个子上下文来在后台执行所有操作:
dispatch_queue_t fetchQ = dispatch_queue_create("Client Fetch", NULL);
dispatch_async(fetchQ, ^{
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
context.parentContext = self.managedObjectContext;
[context performBlock:^{
[self refreshPersonalClientInformation];
dispatch_async(dispatch_get_main_queue(), ^{
[self reload];
});
}];
});
关于ios - 核心数据托管上下文未保存在多线程环境中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20876922/