gpt4 book ai didi

objective-c - 保存时核心数据和多线程崩溃

转载 作者:行者123 更新时间:2023-12-03 13:05:20 30 4
gpt4 key购买 nike

我正在构建一个从远程服务器提取数据并将其存储在CoreData SQLite数据库中的应用程序。我正在从后台线程获取数据,而主线程正在使用它。这是我正在使用的主要方法。

  • 所有的后台线程都有自己的NSManagedObjectContext
  • 上下文之间共享persistentStoreCoordinator
  • 在后台线程上的每次获取时,我保存:插入的对象,并重置:本地上下文。
  • 使用通知我与主线程上下文进行合并。

  • 我遇到的问题:
  • 在后台线程save:操作上,我随机崩溃,但没有消息(设置了NSZombie和Crash Breakpoints)。
  • 正在生成大量重复数据。 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;
    }

    订阅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];
    }

    最佳答案

    好吧,我已经弄清楚了。现在它的工作就像一种魅力。多线程上下文的实现是正确的。问题出在applicationDidBecomeActive:上。我的应用程序使用CoreLocation围墙获取功能列表。当应用程序首次启动时,CoreLocation框架会向用户显示一条警报消息,称该应用程序使用了用户位置...该警报再次调用applicationDidBecomeActive:,从而创建了两个并发的更新。刚刚将我的WebserviceDataModel移到一个属性并实现了一个标志,以了解其是否在运行。而已

    只是为了最终改进,将合并策略更改为NSMergeByPropertyStoreTrumpMergePolicy,所以现在(内存中的)服务器端数据胜过本地存储。

    关于objective-c - 保存时核心数据和多线程崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10499331/

    30 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com