Core Data MagicalRecord:获取请求并保存在多线程中。锁定获取的对象?

Posted

技术标签:

【中文标题】Core Data MagicalRecord:获取请求并保存在多线程中。锁定获取的对象?【英文标题】:Core Data MagicalRecord: fetch request and save in multithreading. Lock fetched objects? 【发布时间】:2014-11-03 12:43:44 【问题描述】:

我正在使用 MagicalRecord。保存一些 ManagedObject(例如“Company”)后,我会立即发送通知以重新加载 Company 的 TableView 并创建其他对象(例如“People”)。

每个方法“addPeople”执行[Company findAllWithPredicate:...@"(lastUpdateDate == nil)"]并生成arrayOfCompany

然后我用enumerateObjectsWithOptions:NSEnumerateConcurrent 迭代arrayOfCompany。 长时间的每次迭代。

作为结果,在下一次拦截通知和调用“addPerson”期间返回公司的相同对象。在每个创建的线程中,我都在使用相同的对象。

在 fetchRequest 期间如何锁定 Company 对象?

代码示例:

先打电话:

+ (void)addCompany

    ...
    [arrayOfCompanies enumerateObjectsWithOptions:NSEnumerateConcurrent
                                      usingBlock:^(Company *obj, NSUInteger idx, BOOL *stop)
    
        [MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext)
            Company *company = [Company createEntityInContext:localContext];
            ....
        
        completion:^(BOOL contextDidSave, NSError *error)
            if (contextDidSave)
            
                [[NSNotificationCenter defaultCenter] postNotificationName:@"newCompanyJustAdded" 
                                                                    object:nil];
            
        ];
    ];

通知捕获:

+ (void)newCompanyJustAdded:(NSNotification *)notification

    [Person addPersons];


+ (void)addPersons

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
        predicate = @"(lastUpdateDate == nil)";
        NSArray *companysInCoreData = [Company findAllWithPredicate:predicate];

        [companysInCoreData enumerateObjectsWithOptions:NSEnumerateConcurrent
                                             usingBlock:^(id obj, NSUInteger idx, BOOL *stop)
        
            NSManagedObjectContext *local_context = [NSManagedObjectContext contextForCurrentThread];
            Company *local_company_obj = [obj inContext:local_context];
            ...
            local_company_obj.lastUpdateDate = [NSDate date];
            [local_context saveToPersistentStoreAndWait];
            ...
            ...
            [MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext)
            
                Person *person = [Person createEntity];
                person.name = ...
                ...
            );
        ];
    );


还有我的第二个问题:

什么是正确的:

[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext)

    [someArray enumerateObjectsWithOptions:usingBlock
    

    
];

[someArray enumerateObjectsWithOptions:usingBlock

    [MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext)

    
];

【问题讨论】:

【参考方案1】:

对于第一个问题,不要选择任何一个选项。相反,请使用NSFetchedResultsController

对于第二个问题,您的第一个选项是正确的选项。您应该打开一个上下文并执行所有更改并让 Magical Record 处理保存所有更改。

如果您选择第二个选项,您仍然会执行相同数量的操作,但您会打开许多​​上下文。

第一个选项:

saveWithBlock: // Called once
enumerateObjectsWithOptions: // Called once

第二个选项

saveWithBlock: // Called many times (once for each object)
enumerateObjectsWithOptions: // Called once

【讨论】:

以上是关于Core Data MagicalRecord:获取请求并保存在多线程中。锁定获取的对象?的主要内容,如果未能解决你的问题,请参考以下文章

Plain Core Data vs Core Data + Magical Record

导入与 Core Data 和 Magical Record 的关系

如何在 Core Data 和 Magical Record 中存储一系列电子邮件

尝试将服务器内容同步到 Core Data 时出现问题 - Magical Record 插入过程非常慢

使用 Magical Record 将对象数组插入 Core Data

设置一对多关系 Core Data 和 Magical Record