高效更新大量NSManagedObject的方法

3
这种问题有很多,但是我找不到关于CoreData的。问题是:我想更新大量的NSManagedObject(可以想象为重置大量NSManagedObject的属性)。目前,我能想到的只有:
1.获取所有对象。 2.使用forin-loop循环遍历所有对象。 3.在每个for块中设置属性。
数据可能很大,我还想为此操作编写一个实用程序。所以问题是:有没有更有效的方法来执行此操作?我不相信使用for-loop是高效的。
额外的问题是:我还想删除满足条件的所有对象(最可能是布尔标志)。我的解决方案与上面类似:
1.使用NSPredicate和条件获取所有对象。 2.使用forin循环遍历所有对象。 3.删除每个对象。
对于解决方案也是同样的问题。
真正的问题是什么?
实际问题是,我想将所有对象的标志(称其为willDelete)设置为YES。然后从服务器同步,然后更新它们并将willDelete设置为NO。之后,任何willDelete为YES的对象都将从上下文中删除。
编辑1:
我的问题可能与this one不同。我想先更新属性。我关心的是性能时间,而不是内存。
编辑2:
好的,我设法使用了NSBatchUpdateRequest。但问题是:我得到了nsmergeConflict。不确定如何处理这个进程。无论如何,这是代码:
- (void)resetProductUpdatedStatus
{
        NSBatchUpdateRequest *request = [NSBatchUpdateRequest batchUpdateRequestWithEntityName:NSStringFromClass([Product class])];
        request.propertiesToUpdate = @{@"hasUpdated" : @(NO)};
        request.resultType = NSUpdatedObjectIDsResultType;
        NSBatchUpdateResult *result = (NSBatchUpdateResult *)[[CoreDataUtil managedObjectContext] executeRequest:request error:nil];
        [result.result enumerateObjectsUsingBlock:^(NSManagedObjectID *objId, NSUInteger idx, BOOL *stop) {
            NSManagedObject *obj = [[CoreDataUtil managedObjectContext] objectWithID:objId];
            if (!obj.isFault) {
                [[CoreDataUtil managedObjectContext] refreshObject:obj mergeChanges:YES];
            }
        }];
}

这将把所有的hasUpdated设置为NO。接下来,我会执行同步进程。使用从同步中捕获的所有产品将更新hasUpdated = YES。接下来执行删除操作:
- (void)updateProductActiveStatus
{
        NSBatchUpdateRequest *request = [NSBatchUpdateRequest batchUpdateRequestWithEntityName:NSStringFromClass([Product class])];
        request.predicate = [NSPredicate predicateWithFormat:@"hasUpdated = NO"];
        request.propertiesToUpdate = @{@"isActive" : @(NO)};
        request.resultType = NSUpdatedObjectIDsResultType;
        [[CoreDataUtil managedObjectContext] executeRequest:request error:nil];
}

正如您所看到的,我已经在更新状态中删除了合并。因此,很可能会在重置状态中引起合并冲突。所以,我想我需要修复合并进展。因此,我会问这里的人是否有任何想法。


可能是如何删除大量核心数据对象的最有效方法的重复问题。 - Saheb Roy
1
如果您的部署目标至少为IOS 8,则可以使用NSBatchUpdateRequest,否则您需要逐个处理每个对象。 - Cy-4AH
@Cy-4AH 我的应用程序目标至少是7。那么你的答案是除了for循环没有其他解决方案吗? - Eddie
@Cy-4AH 兄弟,NSBatchUpdateRequest 的可用性是 iOS 5.0 及更高版本。这可能有效。让我测试一下。 - Eddie
请查看我在此处的答案:https://stackoverflow.com/a/66635329/1703291 - MMujtabaRoohani
1个回答

1

在这里,您还可以检查徽章更新所需的时间比普通更新要少得多。因为在批量更新中,我们不需要从文件本身获取数据。还请检查我的Github链接:https://github.com/tapashm42/CoreDataInSwift.git。 我也正在处理批量删除部分。

func batchUpdate(entityName: String,context:NSManagedObjectContext)  {
        let batchUpdateRequest = NSBatchUpdateRequest(entityName: entityName)
        batchUpdateRequest.propertiesToUpdate = ["name":"Tapash Mollick","designation":"Associate IT Consultant"]
        batchUpdateRequest.resultType = .updatedObjectIDsResultType
        do {
            let start = Date().currentTimeMillis
            let batchUpdateResult = try context.execute(batchUpdateRequest) as! NSBatchUpdateResult
            let result = batchUpdateResult.result as! [NSManagedObjectID]
            print("time taken to update\(Date().currentTimeMillis - start)")
            for objectId in result {
                let manageObject = context.object(with: objectId)
                if (!manageObject.isFault) {
                context.stalenessInterval = 0
                context.refresh(manageObject, mergeChanges: true)
                }
            }
        }
        catch{
            fatalError("Unable to batchUpdate")
        }
    }

extension Date{
    var currentTimeMillis: Int64 {
        return Int64(Date().timeIntervalSince1970 * 1000)
    }
}

如果我想更新所有属性,我应该将propertiesToUpdate设置为什么? - daniel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接