我正在构建一个从远程服务器提取数据并将它们存储在 CoreData SQLite 数据库中的应用程序。我正在从后台线程获取数据,而主线程正在使用它。以下是我正在使用的主要方法。
- 所有后台线程都有自己的
NSManagedObjectContext
. persistentStoreCoordinator
是在上下文之间共享的。- 在后台线程的每次提取中,我保存:插入的对象并重置:本地上下文。
- 使用通知我与主线程上下文进行合并。
我遇到的问题:
- 随机我
NSZombie
在后台线程保存时遇到没有消息的崩溃(并且设置了崩溃断点):操作。 - 有很多重复的数据正在生成。网络服务数据肯定没问题,所以服务器端没有问题。
这里是代码。
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;
}
订阅 WebserviceDataModel 上的 NSManagedObjectContextDidSaveNotification
- (id)init
{
self = [super init];
if (self) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contextChanged:) name:NSManagedObjectContextDidSaveNotification object:nil];
}
return self;
}
WebserviceDataModel 上的 contextChanged: 方法
- (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];
}