ios - 核心数据栈结构

标签 ios swift core-data background-process nsmanagedobjectcontext

我正在用 Swift 实现一个程序,我正在使用 Core Data 框架。我的应用程序已完成,但我决定重构核心数据堆栈。现在,我的 Core Data Stack 结构如下所示:

enter image description here

我查看了 Big Ranch Nerd 和 Github 上其他一些人的 Core Data Stack,大多数时候,他们的 Core Data Stack 看起来像这样:

enter image description here

我想知道是否有更好的方法以类似的方式重构我的 Core Data Stack。简而言之,这就是我将 Managed Object Context 用于:

  • mainContext = 用于所有与 UI 相关的任务
  • firstPrivateContext = 用于从 Firebase 导入所有数据并在登录时将数据推送到持久存储
  • secondPrivateContext = 用于在登录和注册时将联系人从设备导入 Core Data
  • thirdPrivateContext = 用于在使用应用程序期间监听来自 firebase 的传入数据

这就是我的应用大致要做的事情。如果有人知道更好的做法,我愿意接受任何建议。

这是我在用户再次登录时使用的代码:

func importDataFromFirebase(){
guard let importContext = importContext else {return}
FirebaseStore.rootRef.childByAppendingPath("users/"+FirebaseStore.rootRef.authData.uid+"/forums").observeSingleEventOfType(.Value, withBlock:{
    snapshot in
    guard let firebaseData = snapshot.value as? NSDictionary else {return}
    guard let uids = firebaseData.allKeys as? [String] else {return}
    importContext.performBlock{
        for uid in uids{
            guard let forum = NSEntityDescription.insertNewObjectForEntityForName("Forum", inManagedObjectContext: importContext) as? Forum else {return}
            FirebaseStore.rootRef.childByAppendingPath("forums/"+uid+"/posts").queryOrderedByKey().observeSingleEventOfType(.Value, withBlock: {
                snapshot in
                            // Saving the chat's messages
                            guard let data = snapshot.value as? NSDictionary else {return}
                            importContext.performBlock{
                    guard let posts = NSEntityDescription.insertNewObjectForEntityForName("Post", inManagedObjectContext: importContext) as? Post else {return}
                    do{
                                            try importContext.save()
                                        }catch let error{
                        // Error
                                        }
                }
            })
        }
    }
})
}

这张图显示了我想要实现的目标:

enter image description here

最佳答案

您可以以任何方式构建您的 CoreData 堆栈,但首先要回答这个问题 - 您想要实现什么行为。 如果您想在导入某些内容时自动更新 UI,那么您的解决方案将不起作用。

persistent store coordinator 之后拥有 private managed object context 的全部意义在于在后台队列中保持繁重的操作(保存到文件)。

如果您想在导入后立即在屏幕上看到更新,您应该在 child private managed object context 中进行导入,其中 parentContext 设置为 main托管对象上下文。要更新 UI,您可以使用 NSFetchedResultsController。这样,无论何时您在 child managed object context 中保存 - 它都会触发通知,该通知将由 NSFetchedResultsController 处理并更新 UI。

不要忘记保存完整堆栈。为 child managed object context 调用 save 以保存到文件中是不够的。

建议写一些保存全栈的方法,像这样:

- (void)saveWithCompletionBlock:(void (^)(NSError *error))completionBlock {

    static dispatch_queue_t queue = NULL;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        queue = dispatch_queue_create("CoreDataSaveQueue", 0);
    });

    //Retain current NSManagedObjectContext to avoid unloading
    __block NSManagedObjectContext *strongSelf = self;
    dispatch_async(queue, ^{

        __block NSManagedObjectContext *context = strongSelf;
        __block NSError *error = nil;

        do {

            [context performBlockAndWait:^{

                if (context != nil && [context hasChanges])
                    [context save:&error];

                context = (nil != error ? nil : context.parentContext);
            }];
        } while (nil != context);

        dispatch_async(dispatch_get_main_queue(), ^{

            if (completionBlock)
                completionBlock(error);
        });

        //Release current NSManagedObjectContext after save completed
        strongSelf = nil;
    });
}

我希望我的解释能帮助您理解您想要如何构建堆栈。

关于ios - 核心数据栈结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39494855/

相关文章:

ios - 我应该在哪里保存文件

ios - 从 Swift 中的 UITableViewCell 子类中获取 IndexPath

ios - 当 inputAccessoryView 出现时,将 Collection View 聊天向上移动

ios - 核心数据后台保存性能问题

swift - 如何防止对多关系 NSManagedObject 在覆盖合并时与 CoreData 中的 Swift 重复?

iOS:如何为两个 UIView 之间的翻转设置动画?

ios - 如何在tableview底部显示上拉刷新控件?

iOS 应用程序 : Swapping rootviewcontroller after performing login using swift has significant delay

ios - 即使重新启动应用程序,也会在标签中保存数字

android - 如何使用 Android SQLite 数据库在 iOS 中填充 CoreData?