Проблема NSFetchedResultsController XCode 7

Xcode 7 beta 6 и NSFetchedResultsController дали мне головную боль сегодня. Если я скомпилирую тот же (с помощью Swift 2 fixes) код с Xcode 6, программа работает на устройстве и симуляторах (iOS 7, iOS8). Однако, если я скомпилирован с Xcode 7 beta 6, программа прерывается на устройстве (iOS 8.4) со следующими сообщениями об ошибках всякий раз, когда я обновляю Core Data.

Я получаю ошибку, подобную приведенной ниже.

CoreData: ошибка: серьезная ошибка приложения. Исключение было обнаружено у делегата NSFetchedResultsController во время вызова -controllerDidChangeContent :. Недопустимое обновление: недопустимое количество строк в разделе 0. Количество строк, содержащихся в существующем разделе после обновления (2), должно быть равно количеству строк, содержащихся в этом разделе, перед обновлением (2), плюс или минус число из строк, вставленных или удаленных из этого раздела (2 вставленных, 1 удаленных) и плюс или минус количество строк, перемещенных в или из этого раздела (0 перемещено в, 0 выведено). с userInfo (null)

Иногда он падает с другой ошибкой, например

Неверный указатель, удаленный из бесплатного списка ***, установите точку останова в malloc_error_break для отладки

//NSFetchedResultsController delegates func controllerWillChangeContent(controller: NSFetchedResultsController) { self.tableView.beginUpdates() } func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) { switch type { case .Insert: self.tableView.insertSections(NSIndexSet(index: sectionIndex), withRowAnimation: .Fade) case .Delete: self.tableView.deleteSections(NSIndexSet(index: sectionIndex), withRowAnimation: .Fade) default: return } } func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) { switch type { case .Insert: print("Insert New: \(newIndexPath) Old: \(indexPath)") tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Fade) case .Delete: print("Delete New: \(newIndexPath) Old: \(indexPath)") tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade) case .Update: print("Update New: \(newIndexPath) Old: \(indexPath)") tableView.reloadRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade) //self.configureCell(tableView.cellForRowAtIndexPath(indexPath!)!, atIndexPath: indexPath!) case .Move: print("Move New: \(newIndexPath) Old: \(indexPath)") tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade) tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Fade) } } func controllerDidChangeContent(controller: NSFetchedResultsController) { self.tableView.endUpdates() } 

для секции .Update я также попытался позвонить

  self.configureCell(tableView.cellForRowAtIndexPath(indexPath!)!, atIndexPath: indexPath!) 

Настроить метод ячейки:

 func configureCell(cell: UITableViewCell, atIndexPath indexPath: NSIndexPath) { let object = self.fetchedResultsController.objectAtIndexPath(indexPath) as! Person //etc } 

Сортировка дескрипторов

 let sortDescriptor = NSSortDescriptor(key: "date", ascending: false) fetchRequest.sortDescriptors = [sortDescriptor] 

Программа всегда сбой. Единственный способ остановить эту проблему – установить delagete на nil, обновить объект и установить delagate обратно в self.

Это ошибка? Если это не так, как я могу это предотвратить? благодаря

Некоторые сообщения об ошибках с аналогичной проблемой

https://forums.developer.apple.com/thread/12184

https://forums.developer.apple.com/thread/4999

iOS 9 – «попытка удалить и перезагрузить один и тот же путь индекса»

Я запускал как версии XCode6, так и XCode7 и печатный метод didChangeObject здесь – это сравнение

XCode6 iOS 8.4

 Update New: Optional(<NSIndexPath: 0xc000000000000016> {length = 2, path = 0 - 0}) Old: Optional(<NSIndexPath: 0xc000000000000016> {length = 2, path = 0 - 0}) 

XCode 7b6 iOS 8.4

 Update New: nil Old: Optional(<NSIndexPath: 0xc000000000000016> {length = 2, path = 0 - 0}) Insert New: Optional(<NSIndexPath: 0xc000000000000016> {length = 2, path = 0 - 0}) Old: Optional(<NSIndexPath: 0xc000000000000016> {length = 2, path = 0 - 0}) 2015-09-01 01:15:37.898 TestProg[3230:200562] *** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit/UIKit-3347.44.2/UITableView.m:1623 2015-09-01 01:15:37.900 TestProg[3230:200562] CoreData: error: Serious application error. An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:. Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (3) must be equal to the number of rows contained in that section before the update (3), plus or minus the number of rows inserted or deleted from that section (1 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out). with userInfo (null) 

Я пробовал несколько вещей, и я считаю, что это ошибка. Как вы можете видеть из моего журнала, хотя я обновляю существующую запись, делегат получает сообщение Insert. Добавление условной проверки на .Insert исправил мою проблему. Я не использую операцию перемещения в таблице. Поэтому такой же условный режим может быть необходим, если вы используете .Move Мой текущий код выглядит следующим образом.

 func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) { switch type { case .Insert: //FIXME: iOS 9 Bug! if indexPath != newIndexPath { tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Fade) } case .Delete: tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade) case .Update: tableView.reloadRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade) // self.configureCell(tableView.cellForRowAtIndexPath(indexPath!)!, atIndexPath: indexPath!) case .Move: tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade) tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Fade) } } 

Я пытался обновить одну запись, несколько записей, и пока я не видел никаких сбоев. я использую

 tableView.reloadRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade) 

метода, но

 self.configureCell(tableView.cellForRowAtIndexPath(indexPath!)!, atIndexPath: indexPath!) 

также работал во время моих тестов.

Кажется, что это происходит со мной при работе на Sim / Device <iOS9 с использованием Xcode 7 beta 6:

 2015-09-01 11:39:05.683 Diabetes Pal[15038:245613] *** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-3347.44.2/UITableView.m:1623 2015-09-01 11:39:14.954 Diabetes Pal[15038:245613] CoreData: error: Serious application error. An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:. Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (4) must be equal to the number of rows contained in that section before the update (4), plus or minus the number of rows inserted or deleted from that section (1 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out). with userInfo (null) Diabetes Pal(15038,0x33291d4) malloc: *** mach_vm_map(size=1048576) failed (error code=3) *** error: can't allocate region securely *** set a breakpoint in malloc_error_break to debug 

Возможное обходное решение – не анимировать изменения (пока это не будет исправлено):

 //MARK: - fetched results controller delegate func controllerWillChangeContent(controller: NSFetchedResultsController) { let ios9 = NSOperatingSystemVersion(majorVersion: 9, minorVersion: 0, patchVersion: 0) if NSProcessInfo().isOperatingSystemAtLeastVersion(ios9) { tableView?.beginUpdates() } } func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) { let ios9 = NSOperatingSystemVersion(majorVersion: 9, minorVersion: 0, patchVersion: 0) if NSProcessInfo().isOperatingSystemAtLeastVersion(ios9) == false { return } //[... rest of delegate implementation ...] } func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) { let ios9 = NSOperatingSystemVersion(majorVersion: 9, minorVersion: 0, patchVersion: 0) if NSProcessInfo().isOperatingSystemAtLeastVersion(ios9) == false { return }//[... rest of delegate implementation ...] } func controllerDidChangeContent(controller: NSFetchedResultsController) { let ios9 = NSOperatingSystemVersion(majorVersion: 9, minorVersion: 0, patchVersion: 0) if NSProcessInfo().isOperatingSystemAtLeastVersion(ios9) == false { tableView?.reloadData() return } tableView?.endUpdates() } 

Я больше не видел эту проблему, когда строил SDK 9.1. Кажется, ошибка исправлена. Можешь попробовать.

  • Удалить объект в основных данных, не соответствует типу элемента Swift Array
  • Основные данные с авариями «От многих до многих отношений»
  • Почему Core Data Назовите таблицы и атрибуты, которые он создает в SQLite с префиксом Z?
  • Быстрое обновление UITableView с новыми данными
  • Swift - Как получить индекс массива с инициализатором?
  • (SWIFT 3) родительский дочерний контекст crash core data (libc ++ abi.dylib: завершение с неперехваченным исключением типа NSException (Recorded Frame))
  • ios - ошибка при вызове viewWillAppear () вручную (Objective-C)
  • Ошибка EXC_BAD_ACCESS (только на симуляторе) при чтении свойства fetchedObjects NSFetchedResultsController
  • Многопоточное приложение Core Data
  • Как обновить существующий объект в основных данных?
  • Основные данные - коллекция __NSCFSet была мутирована, будучи перечислимой
  • Interesting Posts

    AudioConverter # FillComplexBuffer возвращает -50 и ничего не конвертирует

    как объявить функцию с несколькими параметрами в iOS

    iOS 8 Safari и jQuery-minicolor: не удается разобрать ответ

    Twitter SLRequest performRequestWithHandler – Не удалось подготовить URL-запрос

    Как изменить ограничения автоматического макета после того, как они установлены при использовании constraintEqualToAnchor ()?

    Может ли обмен сообщениями между серверами использовать APNS?

    Могу ли я воспроизводить звук на watchOS 2 с помощью WKAudioFilePlayerItem без гарнитуры bluetooth?

    ECSlidingViewController Базовая настройка жестов и раскрытия меню

    Настройка UIImagePickerController

    Как сделать стиль LightContent в стиле UIImagePickerController StatusBar?

    Чтобы сделать его доступным в App Store, примите условия последнего соглашения в соглашениях, налоге и банковском обслуживании

    Должен ли я использовать тот же элемент ViewController для работы как модально, так и при нажатии?

    CNContact измененная дата и контакты изменены

    Кто-нибудь смог получить групповые звонки, работающие с Kurento на iOS с сетями только для IPv6, как того требует Apple?

    Дерево TableView с несколькими NSMutablearray

    Давайте будем гением компьютера.