iPhone Coredata错误(NSMergeConflict for NSManagedObject)

问题描述 投票:16回答:5

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

抱歉我的英语:)

conflictList =(NSMergeConflict(0xd447640)for NSManagedObject(0xd41b370)with objectID'0xd41b500'with oldVersion = 4 and newVersion = 5 and old object snapshot = {\ n album = \“{(\ 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 gradu = 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 photosNumber = 0; \ n pid = 196997145; \ n src = \\”http://cs10609.vkontakte.ru/u79185807/1215 94781 / 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 gradua tion = 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}“);

iphone core-data
5个回答
32
投票

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

有几个选择:

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

8
投票

我得到了相同的合并冲突,同时保存了上下文。看到苹果医生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();
    }
  } }

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
}()

1
投票

这可能是半解析,也许:)例如,你有以下代码,它存在于N个对象中(每个对象都在单独的线程中并且在同一时间创建(+ -10ms)):

[coreObject addLinkedObject:linkedObject1];

在上下文中处理例程的时间约为70ms。如果您只是将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];
            }
        }
}

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


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
}()
© www.soinside.com 2019 - 2024. All rights reserved.