换句话说,是否可以通过丢弃当前上下文来确定是否会丢失更改?现在我的用户界面显示了context.hasChanges == TRUE
数据丢失的风险,但我认为hasChanges
看起来像这样:
- (BOOL) hasChanges {
return self.updatedObjects > 0 || self.insertedObjects.count > 0 || self.deletedObjects.count > 0;
}
... updatedObjects
包含仅已编辑的对象,即使属性未从其原始值更改也是如此。 updatedObjects
还包含具有瞬态变化的对象。保存这些对象不会修改持久存储。
如果用户实际上没有改变任何内容,我不想提示我的用户保存,那么确定持久属性是否有更改的最佳方法是什么?
答案 0 :(得分:2)
也许您可以使用committedValuesForKeys:
来获取所谓更改密钥的旧值并与新值进行比较。像这样:
@interface NSManagedObject (tofustew)
- (BOOL)isActuallyUpdated;
@end
@implementation NSManagedObject (tofustew)
- (BOOL)isActuallyUpdated {
NSArray *keys = self.changedValues.keyEnumerator.allObjects;
NSDictionary *newValues = [self dictionaryWithValuesForKeys:keys];
NSDictionary *oldValues = [self committedValuesForKeys:self.changedValues.keyEnumerator.allObjects];
return [oldValues isEqualToDictionary:newValues];
}
@end
@interface NSManagedObjectContext (tofustew)
- (BOOL)hasActualChanges;
@end
@implementation NSManagedObjectContext (tofustew)
- (BOOL)hasActualChanges {
if (self.insertedObjects.count > 0 || self.deletedObjects.count > 0)
return YES;
for (NSManagedObject *object in self.updatedObjects) {
if (object.isActuallyUpdated) {
return YES;
}
}
return NO;
}
@end
答案 1 :(得分:2)
由于您只关心是否存在更改,而不是确切地知道更改的内容,因此我会使用hasPersistentChangedValues
上的NSManagedObject
方法来过滤上下文的字段。例如,
NSPredicate *hasChanges = [NSPredicate predicateWithFormat:@"hasPersistentChangedValues = YES"];
BOOL changesExist = ([[context.updatedObjects filteredSetUsingPredicate:hasChanges] count] > 0);
相同的逻辑适用于插入和删除的对象。
答案 2 :(得分:0)
此SO帖子解决了类似的问题:
Identifying which fields have changed before CoreData saves
此方法仅报告对定义为的属性的更改 接收器的持久属性,而不是瞬态变化 属性或自定义实例变量。这种方法没有 不必要的火灾关系错误。
就像过滤updatedObjects
一样简单:
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"changedValues[SIZE] > 0"];
NSSet *objectsWithChangedValues = [context.updatedObjects filteredSetUsingPredicate:predicate];
几行代码产生了预期的结果,但我仍然对updatedObjects
为何如此工作感到困惑......
答案 3 :(得分:0)
我最终在Swift中编写了以下方法:
/// Checks whether there are actually changes that will change the persistent store.
/// The `hasChanges` method would return `true` for transient changes as well which can lead to false positives.
var hasPersistentChanges: Bool {
return !insertedObjects.isEmpty || !deletedObjects.isEmpty || updatedObjects.first(where: { $0.hasPersistentChangedValues }) != nil
}
与以下saveIfNeeded方法结合使用,只会导致必须保存:
/// Saves the context, only if it has any changes and if it has a place to save the changes to (parent or persistent store). Calling this method instead of the regular save() will increase performance. It is also useful to use this function when having a memory store, since this configuration doesn't have a persistent store but may use parent contexts to save their changes to.
/// - throws: A Core Data NSError when saving fails.
/// - returns: Whether the save was needed.
@discardableResult public func saveIfNeeded() throws -> Bool {
let hasPurpose = parent != nil || persistentStoreCoordinator?.persistentStores.isEmpty == false
guard hasPersistentChanges && hasPurpose else {
// Saving won't do anything now, except for decreasing performance. Skip it for now.
return false
}
try save()
return true
}