Bit*_*are 5 core-data ios swift swift4 xcode9
我有一个应用程序,它将与服务器同步,并每天更新数据。在同步期间,我删除了某些实体的所有数据,并重新加载了新数据。我正在使用以下代码:
func SyncronizeUserComments(theData : [[AnyHashable : Any]])
{
// Delete User Comments for this User and Connection
let commentRequest : NSFetchRequest<NSFetchRequestResult> = PT_UserComments.fetchRequest()
commentRequest.predicate = NSPredicate(format: "connection = %@ AND user == %@", Global_CurrentConnection!, Global_CurrentUser!)
coreData.processDeleteRequest(request: commentRequest)
// ADD the Comments to CoreData
for index in 0..<theData.count {
let result : [AnyHashable : Any] = theData[index]
if let commentID = result["Comment_ID"] as? String, let commentText = result["Comment_Text"] as? String, let commentTitle = result["Comment_Title"] as? String
{
let newUserComment = PT_UserComments(context: coreData.persistentContainer.viewContext)
newUserComment.connection = Global_CurrentConnection
newUserComment.user = Global_CurrentUser
newUserComment.comment_ID = commentID
newUserComment.comment_Text = commentText
newUserComment.comment_Title = commentTitle
}
}
// Add the User Comments
print("Added New User Comments: \(theData.count)")
coreData.saveContext()
}
func processDeleteRequest(request : NSFetchRequest<NSFetchRequestResult>)
{
let deleteRequest = NSBatchDeleteRequest(fetchRequest: request)
deleteRequest.resultType = .resultTypeObjectIDs
do {
let result = try coreData.persistentContainer.viewContext.execute(deleteRequest) as? NSBatchDeleteResult
let objectIDArray = result?.result as? [NSManagedObjectID]
let changes = [NSDeletedObjectsKey : objectIDArray]
NSManagedObjectContext.mergeChanges(fromRemoteContextSave: changes as Any as! [AnyHashable : Any], into: [coreData.persistentContainer.viewContext])
} catch {
fatalError("Fatal Error Deleting Data: \(error)")
}
coreData.saveContext()
}
Run Code Online (Sandbox Code Playgroud)
当我调用coreData.saveContext()时,我将对已删除的数据产生合并冲突。
在阅读有关CoreData和NSBatchDeleteRequest的内容时,这会在SQL LITE级别删除,并绕过内存缓存。
我能够使它起作用的唯一方法是设置:
context.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy
Run Code Online (Sandbox Code Playgroud)
这是正确的,还是我做错了什么?我也在Core Data Stack的saveContext()中设置此合并策略。
我刚刚花了几个小时调试同样的问题,希望这可以帮助别人。
问题是NSManagedObjectContext.mergeChanges(fromRemoteContextSave:, into:)更新托管对象上下文,但不更新已删除对象关系的行缓存版本号以匹配Z_OPT数据库文件中更新的版本号 ( ),从而导致保存时不匹配。
如果您使用NSErrorMergePolicyType此选项,即使除版本号之外的所有内容都匹配,也会导致下一次保存失败(甚至当关系标记为保存时,稍后的保存也会失败)。我没有在相关文档或 WWDC 视频中看到这一点,但我猜苹果认为人们总是会选择非默认合并策略。
因此NSMergeByPropertyStoreTrumpMergePolicy,正如问题中提到的,选择解决了这个问题,但您可能不希望对所有保存操作使用此策略。为了避免这种情况,我最终编写了一个仅解决版本不匹配问题的自定义合并策略。代码如下(这是未经测试的 Swift,正如我最初在 Obj-C 中编写的,但应该是等效的):
//Configure the merge as below before saving
context.mergePolicy = AllowVersionMismatchMergePolicy(merge: .errorMergePolicyType)
//...
//The custom merge policy
class AllowVersionMismatchMergePolicy: NSMergePolicy {
override func resolve(optimisticLockingConflicts list: [NSMergeConflict]) throws {
do {
//if the default resolve worked leave it alone
return try super.resolve(optimisticLockingConflicts: list)
} catch {
//if any of the conflict is not a simple version mismatch (all other keys being equal), fail
let hasValueConflict = list.contains { conflict -> Bool in
//compare object and row cache
if let objectSnapshot = conflict.objectSnapshot as NSObject?,
let cachedSnapshot = conflict.cachedSnapshot as NSObject? {
return !objectSnapshot.isEqual(cachedSnapshot)
}
//compare row cache and database
if let cachedSnapshot = conflict.cachedSnapshot as NSObject?,
let persistedSnapshot = conflict.persistedSnapshot as NSObject? {
return !cachedSnapshot.isEqual(persistedSnapshot)
}
//never happens, see NSMergePolicy.h
return true
}
if hasValueConflict {
throw error
}
//Use store rollback merge policy to resolve all the version mismatches
return try NSMergePolicy.rollback.resolve(optimisticLockingConflicts: list)
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
212 次 |
| 最近记录: |