2014-08-31 21 views
8

Mam pewne problemy z usunięciem wiersz z mojego Tableview w Swift, iOS 8, Xcode 6 Beta 6. Za każdym razem staram się usunąć wiersz pojawia się błąd wzdłuż liniisystemów iOS 8 Swift: deleteRowsAtIndexPaths wywala

awaria

Assertion w - [UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-3302.3.1/UITableView.m:1581 30.08.2014 20: 31: 00,971 Klasa katalog [13290: 3241692] ** * Kończenie aplikacji ze względu na nieprzechwycony wyjątek "NSInternalInconsistencyException", przyczyna: "Nieprawidłowa aktualizacja: niepoprawna liczba wierszy w sekcji 1. Liczba wierszy zawartych w istniejącym se ction po aktualizacji (25) musi być równy liczbie wierszy zawartych w tej sekcji przed aktualizacją (25), plus lub minus liczba wierszy wstawionych lub usuniętych z tej sekcji (0 wstawionych, 1 usuniętych) i plus lub minus liczba wierszy przeniesionych do lub z tej sekcji (0 wprowadzono, 0 przesunięto).

Przeczytałem wszystkie odpowiedzi na ten częsty problem tutaj i czuję, że spełniłem zalecane warunki. Pozycja wydaje się być do usunięcia z modelu danych - kiedy przeładowuję aplikację, usunięty element zniknął z tabeli - ale wydaje się, że w odpowiednim pliku sqlite są pewne pozostałości i oczywiście matematyka nie działa t sumują się. W println, który wypluwa indexPath, pokazuje poprawną sekcję i wiersz. Jestem bardzo zaintrygowany. To powinno być proste, ale brakuje mi czegoś głupiego, jestem pewien, podejrzewam, że w procesie usuwania danych. Pełny projekt na Github.

func numberOfSectionsInTableView(tableView: UITableView!) -> Int { 

    return fetchedResultController.sections.count 

} 


func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int { 
    return fetchedResultController.sections[section].numberOfObjects 

    } 

func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! { 
    let cell = tableViewMain.dequeueReusableCellWithIdentifier("CellMain", forIndexPath: indexPath) as UITableViewCell 

     let personForRow = fetchedResultController.objectAtIndexPath(indexPath) as Person 
     cell.textLabel.text = personForRow.fullName() 

     return cell 

} 

func tableView(tableView: UITableView!, canEditRowAtIndexPath indexPath: NSIndexPath!) -> Bool { 
    return true 
} 

func tableView(tableView: UITableView!, editingStyleForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCellEditingStyle { 
    return UITableViewCellEditingStyle.Delete 
} 

func tableView(tableView: UITableView!, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath!) { 
    println("section and row \(indexPath.section) \(indexPath.row) ") 
    if (editingStyle == UITableViewCellEditingStyle.Delete) { 
    let personForRow : NSManagedObject = fetchedResultController.objectAtIndexPath(indexPath) as Person 
    context?.deleteObject(personForRow) 
    context?.save(nil) 
     tableViewMain.beginUpdates() 
    tableViewMain.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Fade) 
     tableViewMain.endUpdates() 
    } 
+3

możliwy duplikat [crash na deleteRowsAtIndexPaths] (http://stackoverflow.com/questions/4186251/crash-on-deleterowsatindexpaths) – durron597

+0

Nie duplikat. Odpowiedzi na te pytania były niewystarczające. –

Odpowiedz

6

Odtwarzanie awarii można łatwo odtworzyć za pomocą szablonu szablonu danych podstawowych Xcode Core Data. Z reguły przy korzystaniu z NSFetchedResultsController powinieneś naprawdę używać NSFetchedResultsControllerDelegate (zadeklarowałeś to, ale go nie używasz).

Usuń te linie w swoim sposobie tableView:commitEditingStyle:forRowAtIndexPath::

tableViewMain.beginUpdates() 
tableViewMain!.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: UITableViewRowAnimation.Fade) 
tableViewMain.endUpdates() 

I dodać te linie do klasy viewController:

func controllerWillChangeContent(controller: NSFetchedResultsController) { 
    tableViewMain.beginUpdates() 
} 

func controller(controller: NSFetchedResultsController!, didChangeSection sectionInfo: NSFetchedResultsSectionInfo!, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) { 
    switch type { 
    case .Insert: 
     tableViewMain.insertSections(NSIndexSet(index: sectionIndex), withRowAnimation: .Fade) 
    case .Delete: 
     tableViewMain.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: 
     tableViewMain.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: .Fade) 
    case .Delete: 
     tableViewMain.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade) 
    case .Update: 
     return 
     //Should also manage this case!!! 
     //self.configureCell(tableView.cellForRowAtIndexPath(indexPath), atIndexPath: indexPath) 
    case .Move: 
     tableViewMain.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade) 
     tableViewMain.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: .Fade) 
    default: 
     return 
    } 
} 

func controllerDidChangeContent(controller: NSFetchedResultsController!) { 
    tableViewMain.endUpdates() 
} 

To powinno rozwiązać problem.

+0

dziękuję za szczegółową odpowiedź. Xcode daje mi błąd z tym kodem. Posiadając zarówno kontroler func (kontroler: NSFetchedResultsController !, didChangeSection i func controller (kontroler: NSFetchedResultsController !, didChangeObject to daje błąd "Definicja konfliktuje z poprzednią wartością" na drugiej funkcji kontrolera.) Jeśli skomentuję pierwszy, błąd zniknie. Wszelkie myśli? –

+0

Ugh, jest późno i wkleiłem kod w środku funkcji commitEditingStyle zamiast w katalogu głównym klasy viewController.To działało doskonale.Muży obowiązek. –

+0

To nie był dokładnie mój problem. kod był taki, że funkcja tableView number of rows nie aktualizowała swojej liczności po usunięciu wiersza. Ten post zasugerował mi, żebym spojrzał na ten fragment mojego kodu: Dziękuję! –

3

Uważam, że jest to po prostu problem z buforowaniem. Twój fetchedResultController nie będzie automatycznie ponownie pobierał twoich wyników, ponieważ buforuje wyniki. Oznacza to, że po ponownym wywołaniu tableView:numberOfRowsInSection:, liczba wyników nadal zwraca 25, mimo że element został usunięty.

+1

@NateBirkholz to wywołanie 'tableView: numberOfRowsInSection' wewnętrznie w' deleteRowsAtIndexPaths'. W ten sposób najpierw drukuje się komunikat o błędzie, ale co ważniejsze, w ten sposób sprawdza, czy wiersze, które próbujesz dodać/usunąć, są naprawdę usuwane z danych. – drewag

+0

Tak, to tam umiera ... Jakieś pomysły dotyczące szczegółów rozwiązania? (Moja początkowa odpowiedź była niepoprawna, dodałem więcej rejestrowania debugowania i masz rację, przepraszam za błąd z mojej strony.) –

+1

@NateBirkholz, może istnieć sposób zmuszenia 'fetchedResultsController' do wyrzucenia pamięci podręcznej. Jednakże, jeśli to ja, zapisałbym wyniki w tymczasowym elemencie tablicy i użyłbym tego dla źródła danych.W ten sposób możesz zarządzać tablicą (usunąć element) samemu i nie martwić się szczegółami implementacji 'fetchedResults' – drewag

Powiązane problemy