我正在構建一個應用程序,它從遠程服務器提取數據並將它們存儲在CoreData SQLite數據庫中。當主線程使用它時,我從後臺線程獲取數據。以下是我正在使用的主要方法。核心數據和多線程崩潰保存
- 所有後臺線程都有自己
NSManagedObjectContext
。 persistentStoreCoordinator
在上下文之間共享。- 在後臺線程的每次提取上,我保存:插入的對象並重置:本地上下文。
- 使用通知我使用主線程上下文合併。
我遇到的問題是:
- 隨機我越來越崩潰,並沒有消息(
NSZombie
和崩潰斷點設置)在後臺線程保存:操作。 - 有很多重複的數據正在生成。 Web服務數據肯定沒問題,所以在服務器端沒有問題。
這是代碼。
的AppDelegate中
- (void)applicationDidBecomeActive:(UIApplication *)application
{
// Update data from remote server
WebserviceDataModel *webservice = [[WebserviceDataModel alloc] init];
webservice.managedObjectContext = self.managedObjectContext;
[webservice startImport];
}
後臺線程取和保存數據上WebserviceDataModel
- (void)startImport
{
dispatch_queue_t downloadQueue = dispatch_queue_create("startImport in WebserviceDataModel", NULL);
dispatch_async(downloadQueue, ^{
NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] init];
moc.persistentStoreCoordinator = self.managedObjectContext.persistentStoreCoordinator;
// get the remote data
NSDictionary *lojas = [Loja allLojasFromRemoteServer];
for (NSDictionary *lojaInfo in lojas) {
Loja *loja __attribute__((unused)) = [Loja lojaWithRemoteData:lojaInfo inManagedObjectContext:moc];
}
if ([moc hasChanges]) {
[moc save:nil];
[moc reset];
}
[moc release];
});
dispatch_release(downloadQueue);
}
的NSManagedObject方法爲對象創建:+ (Loja *)lojaWithRemoteData:inManagedContext:
+ (Loja *)lojaWithRemoteData:(NSDictionary *)remoteData inManagedObjectContext:(NSManagedObjectContext *)context
{
Loja *loja = nil;
NSFetchRequest *request = [[NSFetchRequest alloc] init];
request.entity = [NSEntityDescription entityForName:@"Loja" inManagedObjectContext:context];
request.predicate = [NSPredicate predicateWithFormat:@"lojaId = %d", [[remoteData objectForKey:@"lojaId"] intValue]];
NSError *error = nil;
loja = [[context executeFetchRequest:request error:&error] lastObject];
[request release];
if (!error && !loja) {
// create the record
loja = [NSEntityDescription insertNewObjectForEntityForName:@"Loja" inManagedObjectContext:context];
loja.lojaId = [remoteData objectForKey:@"lojaId"];
loja.email = [remoteData objectForKey:@"email"];
loja.facebook = [remoteData objectForKey:@"facebook"];
// ... and others...
}
return loja;
}
認購到NSManagedObjectContextDidSaveNotification上WebserviceDataModel
- (id)init
{
self = [super init];
if (self) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contextChanged:) name:NSManagedObjectContextDidSaveNotification object:nil];
}
return self;
}
的contextChanged:方法上WebserviceDataModel
- (void)contextChanged:(NSNotification*)notification
{
if ([notification object] == self.managedObjectContext) return;
if (![NSThread isMainThread]) {
[self performSelectorOnMainThread:@selector(contextChanged:) withObject:notification waitUntilDone:YES];
return;
}
[[self managedObjectContext] mergeChangesFromContextDidSaveNotification:notification];
}
嗯,我已經知道了。現在它的功能就像魅力一樣。多線程上下文的實現是正確的。問題出在'applicationDidBecomeActive:'我的應用程序使用CoreLocation Fence來獲取功能列表。當應用程序第一次啓動時,CoreLocation框架會向用戶顯示警告消息,說明應用程序使用de用戶位置...該警報再次調用「applicationDidBecomeActive:」,創建兩個併發的更新波。只是將我的** WebserviceDataModel **移動到一個屬性並實現了一個標誌,以瞭解它是否正在運行。而已。 –