Ошибка Coredata iPhone (NSMergeConflict для NSManagedObject) - PullRequest
16 голосов
/ 10 декабря 2010

Иногда у меня эта ошибка с coredata в том же месте.Иногда это нормально, а в другое время у меня есть эта ошибка.Что это значит?Я ничего не могу найти по этому поводу: (

ps извините за мой английский:)

конфликтаList = ("NSMergeConflict (0xd447640) для NSManagedObject (0xd41b370) с objectID '0xd41b500'со oldVersion = 4 и newVersion = 5 и старым снимком объекта = {\ n album = \ "{(\ n)} \"; \ n audios = \ "{(\ n)} \"; \ n bdate = \ "\ "; \ n city = \" \ "; \ n country = \" \ "; \ n dialog = \" {(\ n)} \ "; \ n domain = \" white.smoke \ "; \ nfaculty = 0; \ n facultyName = \ "\"; \ n firstName = White; \ n градация = 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 (объект: Photo; id: 0xd482c50; данные: {\ n помощь= 121594781; \ n album = nil; \ n comments = \\ "\\"; \ n commentsCount = 0; \ n созданный = \\ "2010-12-10 03:45:01 GMT \\"; \ nowner = \\ "0xd41b500 \\"; \ n \\ "owner_id \\" = 79185807; \ n photosNumber = 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 созданный = \\ "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; \ n statuses = \" {(\ n)} \ "; \ n часовой пояс = 0; \ n uid = 79185807; \ n университет = 0; \ n universityName = \" \ "; \ n videos = \" {(\ n)} \ "; \ n стена= \ "{(\ n)} \"; \ n wallPostsCount = 0; \ n wallReplies = \ "{(\ n (сущность: WallReply; id: 0xd448270; данные:) \ n)} \"; \ n wallSender= \ "{(\ n)} \"; \ n} и новая кэшированная строка = {\ n bdate = \ "\"; \ n city = \ "\"; \ n country = \ "\"; \ ndomain = \ "white.smoke \"; \ n faculty = 0; \ n facultyName = \ "\"; \ n firstName = White; \ n выпускной = 0; \ n homePhone = \ "\"; \ n isFriend =1; \ n isMe = 0; \ n lastName = Smoke; \ n mobilePhone = \ "\"; \ n nickName = \ "\"; \ n онлайн = 1; \ n фото = \ "\"; \ nphotoBig = \ "\"; \ n photoMedium = \ "\"; \ n photoRec = \ "http://cs10609.vkontakte.ru/u79185807/e_8c949409.jpg\";\n rate = \" - 19 \ "; \ n sex = 0; \ n часовой пояс = 0; \ n uid =79185807; \ n университет = 0; \ n университетName = \ "\"; \ n wallPostsCount = 0; \ n} ");

Ответы [ 5 ]

32 голосов
/ 10 декабря 2010

Иногда возникает конфликт слияния, когда ваша база данных изменяется из двух разных мест, а затем сохраняется из двух разных мест; в некоторых случаях изменения могут затрагивать одни и те же объекты или свойства, и Базовые данные не перезаписывают их автоматически, поскольку это может привести к уничтожению ценных данных.

Есть несколько вариантов:

  • Когда вы получаете конфликт слияния, просматривайте его информацию и вручную разрешайте любые конфликты в соответствии с потребностями вашего приложения.
  • Установите политику слияния контекста (ов) управляемого объекта на ту, которая будет автоматически разрешать определенные виды конфликтов. Некоторые политики слияния являются частично деструктивными, а некоторые очень деструктивными - какой из них правильный, действительно зависит от вашего приложения и важности сохраняемых данных.
  • Используйте mergeChangesFromContextDidSaveNotification: для быстрой и тесной интеграции изменений в контексты управляемого объекта, которые еще не были сохранены. Обратите внимание, что для этого может потребоваться разрешить конфликты определенного уровня, но это должно помочь свести к минимуму серьезность.
9 голосов
/ 28 апреля 2015

Вкратце - включите политику слияния, добавьте это в настройку MOC:

Objective-C

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

Swift

 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
}()
8 голосов
/ 30 января 2014

Я получил тот же конфликт слияния, сохраняя контекст.смотри apple doc здесь

Я разрешил конфликты с помощью NSMergePolicy

- (BOOL)resolveConflicts:(NSArray *)list error:(NSError **)error

установил policyType на NSOverwriteMergePolicyType при создании объекта NSMergePolicy

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();
    }
  } }
1 голос
/ 30 августа 2018

Swift 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
}()
1 голос
/ 02 июля 2012

Возможно, это полуразрешение :) Например, у вас есть следующий код, который существует в N объектах (каждый из них находится в отдельном потоке и создается одновременно (+ -10 мс)):

[coreObject addLinkedObject:linkedObject1];

Время обработки процедуры в контексте составляет около 70 мс.если вы просто установите NSMergePolicy (например): NSOverwriteMergePolicy , у вас будет Last-In-Changes: только последний объект будет добавлять ссылку, поскольку каждый контекст является моментальным снимком в памяти постоянного хранилища.Таким образом, каждый моментальный снимок создается во время обычного создания объекта.Задержка обработки в 70 мс приводит к тому, что информация coreObject устарела при ее сохранении.Другими словами, у вас будет только одна сохраненная ссылка или ошибка слияния.Конечно, вы можете подписаться на NSManagedObjectContextObjectsDidChangeNotification, но в этом случае у вас будет N!подписанные отношения или вы можете подписаться в звездной форме через главный контекст в главном потоке, но иногда это не сработало (я использую MagicalRecord, Copyright 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];
            }
        }
}

В этом случае риск минимален.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...