2016-04-11 2 views
1

У меня была проблема с NSFetchedResultsController.nsfetchedResultsController - ошибка при объединении данных

Я был подкласс FRC

class InboxFetchResultsController: NSFetchedResultsController { 

    override init() { 
     let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate 

     let fetchRequest = NSFetchRequest(entityName: "Compliment") 

     let firstSortDescriptor = NSSortDescriptor(key: "updatedAt", ascending: false) 
     let secondSortDescriptor = NSSortDescriptor(key: "sendedDate", ascending: false) 
     fetchRequest.sortDescriptors = [firstSortDescriptor, secondSortDescriptor] 
     let privateManagedObjectContext = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType) 
     privateManagedObjectContext.parentContext = appDelegate.cdh.managedObjectContext 
     let user = try! privateManagedObjectContext.existingObjectWithID(CoreDataManager.sharedInstance.getLoggedUser().objectID) as! User 

     let predicate = NSPredicate(format: "recievedBelong = %@", user) 

     fetchRequest.predicate = predicate 

     super.init(fetchRequest: fetchRequest, managedObjectContext: privateManagedObjectContext, sectionNameKeyPath: nil, cacheName: nil) 
// 
     NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(contextDidSaveContext(_:)), name: NSManagedObjectContextDidSaveNotification, object: nil) 
    } 


    deinit{ 
     NSNotificationCenter.defaultCenter().removeObserver(self) 
    } 

    func contextDidSaveContext(notification: NSNotification) { 
     let sender = notification.object as! NSManagedObjectContext 
     if sender != managedObjectContext { 
      self.managedObjectContext.performBlock({ [weak self] in 
       DDLogInfo("Core data merging") 
       self!.managedObjectContext.mergeChangesFromContextDidSaveNotification(notification) 
      }) 

     } 
    } 

} 

И ComplimentsViewController

lazy var fetchedResultsController: NSFetchedResultsController = { 
    let fetchedResultsController = InboxFetchResultsController() 
    fetchedResultsController.delegate = self 
    fetchedResultsController.fetchRequest.predicate = self.receivedPredicate 
    return fetchedResultsController 
}() 

В viewDidLoad я звоню

func performFetch() { 
    fetchedResultsController.managedObjectContext.performBlock { [weak self] in 
     do { 
      try self!.fetchedResultsController.performFetch() 
     } catch { 
      let fetchError = error as NSError 
      print("\(fetchError), \(fetchError.userInfo)") 
     } 
     dispatch_async(dispatch_get_main_queue(), { 
      self!.tableView.reloadData() 
     }) 
    } 

с

extension ComplimentsViewController: NSFetchedResultsControllerDelegate { 
    func controllerWillChangeContent(controller: NSFetchedResultsController) { 
     dispatch_async(dispatch_get_main_queue(), { 
      self.tableView.beginUpdates() 
     }) 
    } 

    func controllerDidChangeContent(controller: NSFetchedResultsController) { 
     dispatch_async(dispatch_get_main_queue(), { 
      self.tableView.endUpdates() 
     }) 

    } 
    func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) { 
     switch (type) { 
     case .Insert: 
      if let indexPath = newIndexPath { 
       tableView.insertRowsAtIndexPaths([indexPath], withRowAnimation: .Fade) 
      } 
      break; 
     case .Delete: 
      if let indexPath = indexPath { 
       tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade) 
      } 
      break; 
     case .Update: 
      if let indexPath = indexPath { 
       tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic) 
      } 
      break; 
     case .Move: 
      if let indexPath = indexPath { 
       tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade) 
      } 

      if let newIndexPath = newIndexPath { 
       tableView.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: .Fade) 
      } 
      break; 
     } 
    } 

Я редактирую выбранный объект в другом представлении, используя ViewModel, который выделяется на фоне контекста. Когда я сохранить этот фоновый контекст, я получаю эту ошибку:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (5) must be equal to the number of rows contained in that section before the update (5), plus or minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).' 
*** First throw call stack: 

я провожу часы, чтобы заботиться о параллельности, часов, чтобы проверить методы делегата Tableview ... И все-таки получить этот вопрос.

+0

Почему вы подклассы NSFRC ?! Ничто из того, что вы делаете в своем подклассе, не требует подкласса. Просто создайте экземпляр NSFRC. Не подклассы. – Fogmeister

ответ

0

Вы используете NSFetchedResultsController, так что вы не должны вызывать:

 


    dispatch_async(dispatch_get_main_queue(), { 
     self!.tableView.reloadData() 
    }) 

 

Поскольку весь метод NSFetchedResultsControllerDelegate здесь, чтобы обновить Tableview, он будет срабатывать автоматически.

Также вам не нужна точка с запятой в Swift, ни break; в вашем switch поведение по умолчанию ломаться, если явно не упомянуть fallthrough

Смежные вопросы