CoreData和线程安全

 我是谁_2502894917 发布于 2023-02-06 19:31

我有一个单身名称CoreDataManager注册mergeContextChangesForNotification在其中:

+ (id) sharedManager{
    static CoreDataManager *mSharedManager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        mSharedManager = [[CoreDataManager alloc] init];
    });
    return mSharedManager;
}

- (id)init
{
    self = [super init];
    if (self) {
        dispatch_async(dispatch_get_main_queue(), ^{
            [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(mergeContextChangesForNotification:)
                                                     name:NSManagedObjectContextDidSaveNotification
                                                   object:nil];
        });
    }
    return self;
}

我收到通知后:

- (void)mergeContextChangesForNotification:(NSNotification *)notification {
        [shareContext  performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:) 
                                        withObject:notification 
                                     waitUntilDone:YES];
}

我有两个问题:

    我应该performSelectorOnMainThread在这里使用吗?因为这个答案说永远不会.我应该把它改成GCD并使用dispatch_get_main_queue??

    注册mergeContextChangesForNotificationin init是否是一种很好的做法,以确保通知始终在主线程中注册?我从这个答案中读到了

Martin R.. 8

使用iOS 5/OS X 10.7中引入的托管对象并发类型,最好使用这些performBlock方法来确保在正确的线程上执行Core Data操作(更确切地说:在正确的队列上).

所以你将创建共享上下文

shareContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];

并合并来自其他上下文的更改

- (void)mergeContextChangesForNotification:(NSNotification *)notification {
    [shareContext performBlock:^{
        [shareContext mergeChangesFromContextDidSaveNotification:notification];
    }];
}

另请注意(如NSManagedObjectContext文档中所述),建议仅从已知上下文注册保存通知.有了object:nil您的注册,因为系统框架使用的核心数据在内部你可能会得到意想不到的通知.

所以你应该只注册你创建的上下文.或者,您可以检查是否从具有相同持久性存储协调器的上下文发送了通知:

- (void)mergeContextChangesForNotification:(NSNotification *)notification {
     NSManagedObjectContext *otherContext = [notification object];
     if (otherContext != shareContext &&
         [otherContext persistentStoreCoordinator] == [shareContext persistentStoreCoordinator]) {
              [shareContext performBlock:^{
                   [shareContext mergeChangesFromContextDidSaveNotification:notification];
              }];
    }
}

最后,始终在其发布的线程上调用通知方法.通知注册的线程无关紧要.因此,不需要将注册分派给主线程.

1 个回答
  • 使用iOS 5/OS X 10.7中引入的托管对象并发类型,最好使用这些performBlock方法来确保在正确的线程上执行Core Data操作(更确切地说:在正确的队列上).

    所以你将创建共享上下文

    shareContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    

    并合并来自其他上下文的更改

    - (void)mergeContextChangesForNotification:(NSNotification *)notification {
        [shareContext performBlock:^{
            [shareContext mergeChangesFromContextDidSaveNotification:notification];
        }];
    }
    

    另请注意(如NSManagedObjectContext文档中所述),建议仅从已知上下文注册保存通知.有了object:nil您的注册,因为系统框架使用的核心数据在内部你可能会得到意想不到的通知.

    所以你应该只注册你创建的上下文.或者,您可以检查是否从具有相同持久性存储协调器的上下文发送了通知:

    - (void)mergeContextChangesForNotification:(NSNotification *)notification {
         NSManagedObjectContext *otherContext = [notification object];
         if (otherContext != shareContext &&
             [otherContext persistentStoreCoordinator] == [shareContext persistentStoreCoordinator]) {
                  [shareContext performBlock:^{
                       [shareContext mergeChangesFromContextDidSaveNotification:notification];
                  }];
        }
    }
    

    最后,始终在其发布的线程上调用通知方法.通知注册的线程无关紧要.因此,不需要将注册分派给主线程.

    2023-02-06 19:35 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有