核心数据堆栈结构

时间:2016-09-14 15:54:54

标签: ios swift core-data background-process nsmanagedobjectcontext

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

enter image description here

我看了Core Data Stack表格Big Ranch Nerd和Github上的其他人,大多数时候,他们的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

1 个答案:

答案 0 :(得分:1)

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

private managed object context之后persistent store coordinator之后的重点是在后台队列中保持繁重的操作(保存到文件)。

如果您希望在导入后立即在屏幕上看到更新,则应在child private managed object context中将parentContext设置为main managed object context进行导入。要更新用户界面,您可以使用NSFetchedResultsController。这样,无论何时保存在child managed object context中,它都会触发通知,该通知将由NSFetchedResultsController处理并更新用户界面。

不要忘记保存完整的堆栈。仅将child managed object context的保存称为保存到文件中是不够的。

建议写一些保存完整堆栈的方法,如下所示:

- (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;
    });
}

我希望我的解释会帮助您了解如何构建堆栈。