2015-08-31 16 views
9

Xcode 7 Beta 6 und und NSFetchedResultsController gab mir Kopfschmerzen heute. Wenn ich denselben (mit Swift 2 Fixes) Code mit Xcode 6 kompiliere, funktioniert das Programm auf Geräten und Simulatoren (iOS 7, iOS8). Wenn ich jedoch mit Xcode 7 Beta 6 kompiliere, stürzt das Programm auf dem Gerät (iOS 8.4) mit folgenden Fehlermeldungen ab, wenn ich Core Data aktualisiere.NSFetchedResultsController XCode 7 Problem

Ich erhalte eine Fehlermeldung ähnlich unter

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 (2) must be equal to the number of rows contained in that section before the update (2), plus or minus the number of rows inserted or deleted from that section (2 inserted, 1 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)

Manchmal mit einem anderen Fehler stürzt wie

Invalid pointer dequeued from free list *** set a breakpoint in malloc_error_break to debug

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

für den .Update Abschnitt Ich habe auch versucht

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

Konfigurieren Zellmethode:

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

Sortieren Descriptors

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

Programm immer abstürzt. Nur um dieses Problem irgendwie zu stoppen, setzen Sie delagete auf null, aktualisieren Sie das Objekt und setzen Sie delagate auf self zurück.

Ist das ein Fehler? Wenn nicht, wie kann ich das verhindern? Dank

Einige Fehlerberichte mit gleichen/ähnlichen Problem

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

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

iOS 9 - "attempt to delete and reload the same index path"

Ich lief beide XCode6 und XCode7 Versionen und gedruckt didChangeObject Methode hier ist der Vergleich

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) 
+0

In meinem aktuellen Projekt verwende ich auch die 'configureCell' Methode, ich denke ich habe sie wegen eines ähnlichen Fehlers geändert. Könnten Sie vielleicht Ihre configure-Zellen-Methode zeigen? – Mundi

+0

es ist mosty boostplate code. Ich habe eine Beziehung von eins zu vielen. Etwas wie unten: func configureCell (Zelle: UITableViewCell, atIndexPath indexPath: NSIndexPath) { Lassen Sie object = self.fetchedResultsController.objectAtIndexPath (indexPath) as! Person // usw. } – Meanteacher

+0

Hat Ihr FRC einen Sortierungsdeskriptor oder ein Prädikat, das sich auf eine Beziehung über den Schlüsselpfad bezieht? Das kann manchmal zu unerwarteten Ergebnissen führen. – Mundi

Antwort

10

Ich habe einige Dinge ausprobiert und ich glaube, dass dies ein Fehler ist. Wie Sie aus meinem Protokoll sehen können, erhält der Delegat, obwohl ich den vorhandenen Datensatz aktualisiere, Nachricht einfügen. Hinzufügen bedingte Überprüfung um .Insert behoben mein Problem. Ich verwende keine Verschiebeoperation in der Tabelle.Daher gleiche Art von bedingter Operation vielleicht auch notwendig, wenn Sie .Move Mein aktuellen Code verwenden, ist wie unter

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

ich versucht habe, einzelnen Datensatz, mehrere Datensätze zu aktualisieren und ich habe keine Abstürze noch bisher gesehen. Ich bin mit

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

Methode aber

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

arbeitete auch während meiner Tests.

+0

Das funktioniert auch für mich. – Chinthaka

+0

Wissen Sie, funktioniert es mit Xcode 7.1 Beta 2? –

+0

Ich habe nur mit Xcode 7.0 Beta 6, GM und Xcode 7.0 Release Build getestet. – Meanteacher

1

Dies scheint mir der Fall zu sein, wenn sie auf Sim/Geräte < iOS9 mit Xcode 7 Beta 6 läuft:

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 

Eine mögliche Abhilfe ist, um die Änderungen nicht zu animieren (bis dieser befestigt ist):

//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() 
} 
+0

Dies löste das Problem. – Chinthaka

0

Ich habe dieses Problem nicht mehr gesehen, wenn ich auf SDK 9.1 baue. Es scheint, dass der Fehler behoben wurde. Du kannst es versuchen.

+0

Nicht für mich behoben –