ios - NSOperationQueue、CoreData 和 MagicalRecord 同步问题

标签 ios multithreading core-data nsoperationqueue magicalrecord

我为一个表的inserting/updating/deleting/searching 相关的所有操作创建了一个NSOperationQueue。我使用 MagicalRecord 进行核心数据操作。但是我在同步方面遇到了一些问题。一个简化的例子如下。

例如。一个名为 person 的表和一个名为 like 的 person 中的列。当用户点击一个按钮时,like 将增加 1。我喜欢做

[SameBackgroundQueue addOperationWithBlock:^{
    User *user = [User MR_findFirstWithPredicate:some_predicate];
    user.like += 1;
    NSManagedObjectContext *localContext = [NSManagedObjectContext MR_contextForCurrentThread];
    [localContext MR_saveToPersistentStoreWithCompletion:^(BOOL success, NSError *error) {
        [SameBackgroundQueue addOperationWithBlock:^{
            [self syncWithServer];//This can take time
    }];
}];

但是,如果用户点击很快,like 就不会正确,因为MR_findFirstWithPredicate 会得到脏记录。问题源于 NSOperationQueue 可以使用不同的线程,而 MR_findFirstWithPredicate 使用当前线程的上下文。因此,它可能会尝试从不同的 NSManagedObjectContext 获取用户,因此它会获取脏数据。

当然如果我们使用mainQueue,我们不会有任何问题。但是,如何使用后台线程并确保没有脏记录问题。如果我在一个特定线程而不是用户 NSOperationQueue 上运行,似乎可以解决整个问题。我应该改用 GCD 吗?


在我之前的项目中,我正在使用

[self createManagedObjectContextWithParent:self.mainQueueManagedObjectContext andConcurrencyType:NSPrivateQueueConcurrencyType];

[managedObjectContext save:&error];
if (managedObjectContext.parentContext) {
    [managedObjectContext.parentContext performBlock:^{
        NSError *parentError = nil;
        [managedObjectContext.parentContext save:&parentError];
    }];
}

我知道有 WWDC 视频在谈论 NSManagedObjectContext 和并发上下文等。但是如果我使用它,我就不能使用 MagicRecord。

任何建议将不胜感激。


实际上我找到了一种更有效的方法。如果我做错了,请纠正我。

我实际上创建了一个通用的 singleton 上下文 [NSManagedObjectContext MR_context] 以供 User OperationQueue 共享。所以即使所有线程访问同一个上下文,它们也不会得到脏数据。

仍然会有小故障,例如,如果两个线程正在更改同一上下文的同一对象怎么办。这通常是非常罕见的情况,但我会看看情况如何。我可能会将最大并发线程设置为一个,只是为了避免这种情况。我不确定它是否会降低性能。明天更新进度。

最佳答案

我建议将您的操作 block 更改为更像这样的内容:

[TheSameQueue addOperationWithBlock:^{
    NSManagedObjectContext *localContext = [NSManagedObjectContext MR_context];

    User *user = [User MR_findFirstWithPredicate:some_predicate inContext:localContext];
    user.like += 1;

    [localContext MR_saveToPersistentStoreWithCompletion:^(BOOL success, NSError *error) {
        [self syncWithServer];//This can take time
    }];
}];

您在默认上下文中执行所有后台操作,您可以将其视为主线程上下文。一般来说,这将在 99% 的时间内工作,但会导致随机死锁和崩溃。此外,MR_contextForCurrentThread 已被弃用,因为它还会导致队列出现问题,即为线程使用错误的上下文。

关于ios - NSOperationQueue、CoreData 和 MagicalRecord 同步问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21691172/

相关文章:

ios - UISplitViewController 仅详细信息 inputAccessoryView

ios - Swift 4 准备(用于 segue :) not being called

ios - "Unrecognized selector sent to instance"在不寻常的地方,使用 CoreData @NSManaged 子类

ios - Apple CoreData 模板中的属性声明

ios - 强制 FBSDK ShareDialog React Native 自动使用浏览器

ios - 如何在IOS中获取上次通话的详细信息

C# 文件移动(重命名) 多线程 Windows 操作系统

c++ - 多次等待同一个锁

c++ - 分离线程执行结束

保存在 Core Data 中的 iOS 数据无法在发布后继续存在