iPhone Coredata错误(NSMergeConflict for NSManagedObject)

时间:2010-12-10 05:19:06

标签: iphone core-data

有时我在同一个地方有coredata这个错误。有时它确定,在其他时间我有这个错误。这是什么意思?我找不到任何关于它的信息:(

抱歉我的英语:)

  

conflictList =(           “NSMergeConflict(0xd447640)for NSManagedObject(0xd41b370)with objectID'0xd41b500'with oldVersion = 4 and newVersion = 5 and old object snapshot = {\ n album = \”{(\ n)} \“; \ n \ n audios = \” {(\ n)} \“; \ n bdate = \”\“; \ n city = \”\“; \ n country = \”\“; \ n dialog = \”{(\ n)} \“ ; \ n domain = \“white.smoke \”; \ n faculty = 0; \ n facultyName = \“\”; \ n firstName = White; \ n graduation = 0; \ n homePhone = \“\”; \ n isFriend = 1; \ n isMe = 0; \ n lastName = Smoke; \ n mobilePhone = \“\”; \ n nickName = \“\”; \ n online = 1; \ n photo = \“\”; \ n photoBig = \“\”; \ n photoComments = \“{(\ n)} \”; \ n photoMedium = \“\”; \ n photoRec = \“http://cs10609.vkontakte.ru/u79185807 /e_8c949409.jpg\";\n photos = \“{(\ n(实体:照片; id:0xd482c50;数据:{\ n aid = 121594781; \ n album = nil; \ n comments = \\”\\ “; \ n commentsCount = 0; \ n created = \\”2010-12-10 03:45:01 GMT \\“; \ n owner = \\”0xd41b500 \\“; \ n \\”owner_id \\ “= 79185807; \ n照片Number = 0; \ n pid = 196997145; \ n src = \\“http://cs10609.vkontakte.ru/u79185807/121594781/m_ \\”; \ n \\“src_big \\”= \\“http ://cs10609.vkontakte.ru/u79185807/121594781/x_ \\“; \ n \\”src_small \\“= \\”http://cs10609.vkontakte.ru/u79185807/121594781/s_ \\“; \ n \\“src_xbig \\”= nil; \ n \\“src_xxbig \\”= nil; \ n wallRel = \\“0xd480840 \\”; \ n}),\ n(实体:照片; id:0xd431570;数据:{\ n aid = 121594781; \ n album = nil; \ n comments = \\“\\”; \ n commentsCount = 0; \ n created = \\“2010-12-10 03:43:01 GMT \\“; \ n owner = \\”0xd41b500 \\“; \ n \\”owner_id \\“= 79185807; \ n photosNumber = 0; \ n pid = 196997029; \ n src = \\”http:/ /cs10609.vkontakte.ru/u79185807/121594781/m_\\";\n \\“src_big \\”= \\“http://cs10609.vkontakte.ru/u79185807/121594781/x_ \\”; \ n \\“src_small \\”= \\“http://cs10609.vkontakte.ru/u79185807/121594781/s_ \\”; \ n \\“src_xbig \\”= nil; \ n \\“src_xxbig \\ “= nil; \ n wallRel = \\”0xd42d500 \\“; \ n})\ n)} \”; \ n rate = \“ - 19 \”; \ n sex = 0; \ nstatuses = \“ {(\ n)} \“; \ n时区= 0; \ n uid = 79185807; \ n university = 0; \ n universityName = \”\“; \ n videos = \”{(\ n)} \“ ; \ n wall = \“{(\ n)} \”; \ n wallPostsCount = 0; \ n wallReplies = \“{(\ n(实体:WallReply; id:0xd448270;数据:) \ n)} \” ; \ n wallSender = \“{(\ n)} \”; \ n}和新缓存的行= {\ n bdate = \“\”; \ n city = \“\”; \ n country = \“\ “; \ n domain = \“white.smoke \”; \ n faculty = 0; \ n facultyName = \“\”; \ n firstName = White; \ n graduation = 0; \ n homePhone = \“\”; \ n isFriend = 1; \ n isMe = 0; \ n lastName = Smoke; \ n mobilePhone = \“\”; \ n nickName = \“\”; \ n online = 1; \ n photo = \“\”; \ n photoBig = \“\”; \ n photoMedium = \“\”; \ n photoRec = \“http://cs10609.vkontakte.ru/u79185807/e_8c949409.jpg \”; \ n rate = \“ - 19 \ “; \ n sex = 0; \ n timezone = 0; \ n uid = 79185807; \ n university = 0; \ n universityName = \”\“; \ n wallPostsCount = 0; \ n}”       );

5 个答案:

答案 0 :(得分:32)

当您的数据库从两个不同的位置更改,然后从两个不同的位置保存时,有时会导致合并冲突;在某些情况下,更改可能会影响相同的对象或属性,Core Data不会自动覆盖它们,因为这可能会破坏有价值的数据。

有几个选择:

  • 当您收到合并冲突时,请迭代其信息,并根据应用程序的需要手动解决任何冲突。
  • 管理对象上下文的
  • Set the merge policy将自动解决某些类型的冲突。一些合并策略具有部分破坏性,有些非常具有破坏性 - 哪一个是正确的,这取决于您的应用程序以及保存数据的重要性。
  • 使用mergeChangesFromContextDidSaveNotification:快速,紧密地将更改集成到尚未保存的托管对象上下文中。请注意,这可能仍需要一定程度的冲突解决,但应有助于最大限度地降低严重性。

答案 1 :(得分:8)

我在保存上下文时遇到了相同的合并冲突。请参阅apple doc here

我使用NSMergePolicy

解决了冲突
- (BOOL)resolveConflicts:(NSArray *)list error:(NSError **)error

在创建NSMergePolicy对象时将policyType设置为NSOverwriteMergePolicyType

  

NSOverwriteMergePolicyType:指定一个策略,用于覆盖冲突中已更改对象的持久存储中的状态。

`

if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {

  NSLog(@"Unresolved error %@, %@", error, [error userInfo]);

  NSArray * conflictListArray = (NSArray*)[[error userInfo] objectForKey:@"conflictList"];
  NSLog(@"conflict array: %@",conflictListArray);
  NSError * conflictFixError = nil;

  if ([conflictListArray count] > 0) {

    NSMergePolicy *mergePolicy = [[NSMergePolicy alloc] initWithMergeType:NSOverwriteMergePolicyType];

    if (![mergePolicy resolveConflicts:conflictListArray error:&conflictFixError]) {
      NSLog(@"Unresolved conflict error %@, %@", conflictFixError, [conflictFixError userInfo]);
      NSLog(@"abort");
      abort();
    }
  } }

答案 2 :(得分:8)

简而言之 - 启用合并政策将此添加到您的MOC设置:

目标-C

[_managedObjectContext setMergePolicy:[[NSMergePolicy alloc] initWithMergeType:NSMergeByPropertyObjectTrumpMergePolicyType]];

夫特

 lazy var managedObjectContext: NSManagedObjectContext? = {

    let coordinator = self.persistentStoreCoordinator
    if coordinator == nil {
        return nil
    }
    var managedObjectContext = NSManagedObjectContext()
    managedObjectContext.persistentStoreCoordinator = coordinator

    //add this line 
    managedObjectContext.mergePolicy = NSMergePolicy(mergeType: NSMergePolicyType.MergeByPropertyObjectTrumpMergePolicyType);

    return managedObjectContext
}()

答案 3 :(得分:1)

它正在解决,也许:) 例如,您有以下代码,它们存在于N个对象中(每个对象都在单独的线程中并且在同一时间(+ -10ms)创建):

[coreObject addLinkedObject:linkedObject1];

在上下文中处理例程的时间约为70毫秒。 如果您只是将NSMergePolicy设置为(例如): NSOverwriteMergePolicy ,您将拥有Last-In-Changes:只有最后一个对象将添加链接,因为每个上下文都是持久存储的内存快照。因此,每个快照都是在例程对象创建的时刻创建的。 70ms处理时间滞后导致 coreObject 的信息太旧,保存时。换句话说,您将只有一个保存的链接或合并错误。当然,您可以订阅NSManagedObjectContextObjectsDidChangeNotification但在这种情况下您将拥有N!订阅关系或者您可以在主线程中以明星方式跨主要上下文订阅,但有时它不起作用(我使用的是MagicalRecord,版权所有2011 Magical Panda Software LLC。)。 我的解决方案是在保存之前重新读取关键coreObject以及使用合适的合并策略:

 @synchronized (self) {
        if ([context hasChanges]) {
            if (needRefresh) {
                [context refreshObject:coreObject mergeChanges:NO];
                [coreObject addLinkedObject:linkedObject1];
            }
            NSError *err = nil;
            [context save:&err];
            if (err) {
                NSLog(@"Error Saving Linked Object: %@", [err userInfo]);
                [context rollback];
            }
        }
}

在这种情况下,风险很小。

答案 4 :(得分:1)

快捷键4

private(set) lazy var mainContext: NSManagedObjectContext = {

    let context = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
    context.parent = privateContext

    context.mergePolicy = NSMergePolicy(merge: .overwriteMergePolicyType)

    // Or we can use Trumping 
    // .mergeByPropertyObjectTrumpMergePolicyType
    // .mergeByPropertyStoreTrumpMergePolicyType

    // Rolling back is another option
    // .rollbackMergePolicyType

    return context
}()