从 Core Data 中的 AppDelegate 执行回滚功能时需要访问相同的 ManagedObjectContext 实例

Need access to same instance of ManagedObjectContext when performing rollback functionality from AppDelegate in Core Data

在我的 iOS 应用程序中,我使用核心数据来获取和删除一个非常大的数据集。此过程大约需要 5-10 秒。我想做的是执行回滚,以防用户决定在该过程完成之前关闭设备。但是,问题是让 NSManagedObjectContext 的 SAME 实例从适当的 AppDelegate 方法调用回滚函数。在我的应用程序中,我使用像这样的 Singleton 对象调用我的核心数据方法:

static MySingleton *sharedSingleton = nil;


+ (MySingleton *) sharedInstance {

    if (sharedSingleton == nil) {
        sharedSingleton = [[super alloc] init];
    }
    return sharedSingleton;
}

在我的应用程序中,我 return 一个像这样的 NSManagedObjectContext 实例:

- (NSManagedObjectContext *) managedObjectContext{

    if (_managedObjectContext != nil) {
        return _managedObjectContext;
    }
    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];

    if (coordinator != nil) {

        _managedObjectContext = [[NSManagedObjectContext alloc]initWithConcurrencyType:NSMainQueueConcurrencyType];
        [_managedObjectContext setPersistentStoreCoordinator:coordinator];

        //Undo Support
        NSUndoManager *anUndoManager = [[NSUndoManager alloc] init];
        [self.managedObjectContext setUndoManager:anUndoManager];
    }
    return _managedObjectContext;
}

然后我调用它,并将其分配给这样的引用:

NSManagedObjectContext *context = [[MySingleton sharedInstance] managedObjectContext];

我如何使这个 ManagedObjectContext 实例可供我在 AppDelegate 中使用,以便我可以调用回滚函数?

作为替代解决方案,您可以创建一个多上下文场景,而不是回滚更改,在该场景中,子托管对象上下文添加您需要的所有数据,最终完成后,您保存子上下文发送新的数据到主要的管理对象。这样,在完成整个过程之前,主要的托管对象上下文不会受到影响。

这篇文章很棒,可以作为参考 Multi-Context CoreData

基本上你需要做的是

// create main MOC
_mainContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[_mainContext setPersistentStoreCoordinator:_persistentStoreCoordinator];

// create child MOC
_childContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
_childContext.parentContext = _mainContext;

希望对您有所帮助。

首先,创建单例的更好(更安全)的方法是此处给出的示例:Create singleton using GCD's dispatch_once in Objective C,即:

+ (instancetype)sharedInstance
{
    static dispatch_once_t once;
    static id sharedInstance;
    dispatch_once(&once, ^{
        sharedInstance = [[self alloc] init];
    });
    return sharedInstance;
}

接下来,由于您已经创建了一个必须停留几秒钟的托管 object 上下文,因此您必须在某处对它有一个强引用,而您确实这样做了。

如果您正在进行调试并质疑有关代码的一些基本假设,请为托管 object 上下文命名(或记录 MOC 指针的内存地址),您可以稍后在调试器中检查,以验证您确实在处理同一个调试器。

另请注意,如果您仅为此类导入创建了专用的托管 Object 上下文,则无需将其回滚。你可以直接丢弃它。

在我的应用程序中,我通常有一个 parent(root)管理的 object 上下文和几个 child 上下文;一个 child 用于主线程,另一个 child 用于导入类型操作。