Ошибка iPhone Coredata (NSMergeConflict для NSManagedObject)
Иногда у меня есть эта ошибка с coredata в том же месте. Иногда это нормально, и в другое время у меня есть эта ошибка. Что это значит? Я ничего не могу найти об этом: (
ps извините за мой английский:)
conflictList = ( "NSMergeConflict (0xd447640) для NSManagedObject (0xd41b370) с объектным идентификатором" 0xd41b500 "с oldVersion = 4 и newVersion = 5 и старым снимком объекта = {\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 graduation = 0;\n homePhone =\" \ ";\n isFriend = 1;\n isMe = 0;\n lastName = Smoke;\n mobilePhone =\" \ ";\n nickName =\" \ ";\n онлайн = 1;\n photo =\" \ ";\n photoBig =\" \ ";\n photoComments =\" {(\n)} \ ";\n photoMedium =\" \ ";\n photoRec =\" http://cs10609.vkontakte.ru/u79185807/e_8c949409.jpg\ ";\n photos =\" {(\n (entity: Photo; id: 0xd482c50; data: {\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 (entity: Photo; 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;\n statuses =\" {(\n)}\ ";\n timezone = 0;\n uid = 79185807;\n university = 0;\n universityName = \" \ ";\n videos = \" {(\n)}\ "\n wall =\" {(\n)} \ ";\n wallPostsCount = 0;\n wallReplies =\" {(\n (объект: WallReply; id: 0xd448270; data:)\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 онлайн = 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 университет = 0;\n universityName = \" \ ";\n wallPostsCount = 0;\n}" );
Ответы
Ответ 1
Конфликт слияния иногда возникает, когда ваша база данных изменяется из двух разных мест, а затем сохраняется из двух разных мест; в некоторых случаях изменения могут влиять на одни и те же объекты или свойства, а Core Data автоматически не перезаписывает их, поскольку это может уничтожить ценные данные.
Есть несколько вариантов:
- Когда вы получаете конфликт слиянием, повторяете его информацию и вручную разрешаете конфликты в соответствии с потребностями вашего приложения.
- Установить политику слияния контекста (ов) управляемого объекта, который будет автоматически разрешать определенные типы конфликтов. Некоторые политики слияния являются частично разрушительными, некоторые из них очень разрушительны, и каждый из них действительно зависит от вашего приложения и важности сохранения данных.
- Используйте mergeChangesFromContextDidSaveNotification:, чтобы быстро и тесно интегрировать изменения в контексты управляемых объектов, которые еще не были сохранены. Обратите внимание, что это может по-прежнему требовать определенного уровня разрешения конфликтов, но должно помочь свести к минимуму серьезность.
Ответ 2
Я получил тот же конфликт слияния, сохраняя контекст. см. 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();
}
} }
Ответ 3
Вкратце - включите Merge Policy, добавьте это в свою настройку MOC:
objective-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
}()
Ответ 4
Это полуразрешение, возможно:)
Например, у вас есть следующий код, который существует в 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];
}
}
}
В этом случае риск минимален.