2015-08-06 1 views
0

Я создаю табличный вид, который имеет расширяемую таблицу с разделами (пучками), являющимися пользовательским UITableViewCell, а также строками (приятелями) - вы можете создавать произвольные пучки друзей. Я также заполняю таблицу, используя NSFetchedResultsController, который я успешно выполнил. Трудность я имею при добавлении кучи к основным данным, NSFetchedResultsController бросает это исключение:Как использовать NSFetchedResultsController для добавления раздела (с пользовательскими ячейками ячеек) в контроллере табличного представления?

CoreData: error: Serious application error. An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:. attempt to insert row 0 into section 1, but there are only 0 rows in section 1 after the update with userInfo (null)

Я хотел бы иметь возможность добавить кучу (в модальном диалоге) и он автоматически отображаться в представлении таблицы (в соответствии с возможностями NSFetchedResultController), но он генерирует исключение (не разбивается), как показано выше, и раздел не добавляется.

Вот код NSFetchedResultsController:

Инициализация (инициализируется при загрузке в виде таблицы)

lazy var fetchedResultsController: NSFetchedResultsController = { 
    let bunchesFetchRequest = NSFetchRequest(entityName: Constants.CoreData.bunch) 
    // Sort bunches by bunch name, in alphabetical order, not caring about capitalization 
    let primarySortDescriptor = NSSortDescriptor(key: Constants.CoreData.Bunch.name, ascending: true, selector: "caseInsensitiveCompare:") 
    bunchesFetchRequest.sortDescriptors = [primarySortDescriptor] 

    // TODO: Answer question: Do we need this, does this benefit us at all, and how does prefetching work? 
    bunchesFetchRequest.relationshipKeyPathsForPrefetching = [Constants.CoreData.Bunch.buddies] 

    let frc = NSFetchedResultsController(
     fetchRequest: bunchesFetchRequest, 
     managedObjectContext: CoreDataStackManager.sharedInstance().managedObjectContext!, 
     sectionNameKeyPath: Constants.CoreData.Bunch.name, 
     cacheName: nil 
    ) 
    frc.delegate = self 
    return frc 
}() 

Таблица Посмотреть Методы

func numberOfSectionsInTableView(tableView: UITableView) -> Int { 
    // sections are the bunches 
    if let sections = fetchedResultsController.sections { 
     return sections.count 
    } 
    return 0 
} 

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
    // sections are the bunches (this is for when sectionNameKeyPath is set) 
    if let sections = fetchedResultsController.sections { 
     let currentSection = sections[section] as! NSFetchedResultsSectionInfo 
     let bunch = currentSection.objects[0] as! Bunch 
     // Return the number of buddies in this section (bunch) 
     return bunch.buddies.count 
    } 
    return 0 
} 


func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { 

    if let sections = fetchedResultsController.sections { 
     let currentSection = sections[section] as! NSFetchedResultsSectionInfo 
     let bunch = currentSection.objects[0] as! Bunch 
      // Create BunchTableViewCell 
     let headerCell: BunchTableViewCell = tableView.dequeueReusableCellWithIdentifier(bunchCellIdentifier) as! BunchTableViewCell 

     headerCell.bunchNameLabel.text = bunch.name  
     return headerCell 
    } 
    return nil 
} 

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 

    let cell: BuddyInBunchTableViewCell = tableView.dequeueReusableCellWithIdentifier(buddyInBunchCellIdentifier, forIndexPath: indexPath) as! BuddyInBunchTableViewCell 

    if let sections = fetchedResultsController.sections { 
     let currentSection = sections[indexPath.section] as! NSFetchedResultsSectionInfo 
     let bunch = currentSection.objects[0] as! Bunch 
     let buddy: Buddy = bunch.getBuddiesInBunch()[indexPath.row] 
     cell.buddyFullNameLabel.text = buddy.getFullName() 
    } 
    return cell 
} 

func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { 
    return 50.0 
} 

NSFetchedResultsController Методы

func controllerWillChangeContent(controller: NSFetchedResultsController) { 
    self.tableView.beginUpdates() 
} 

func controller(
    controller: NSFetchedResultsController, 
    didChangeObject anObject: AnyObject, 
    atIndexPath indexPath: NSIndexPath?, 
    forChangeType type: NSFetchedResultsChangeType, 
    newIndexPath: NSIndexPath?) { 

     switch type { 
     case NSFetchedResultsChangeType.Insert: 
      // Note that for Insert, we insert a row at the __newIndexPath__ 
      if let insertIndexPath = newIndexPath { 
       // AAAAAAAAAA 
       self.tableView.insertRowsAtIndexPaths([insertIndexPath], withRowAnimation: UITableViewRowAnimation.Fade) 
       // BBBBBBBBBB 
       // self.tableView.insertSections(NSIndexSet(index: insertIndexPath.section), withRowAnimation: UITableViewRowAnimation.Fade) 
      } 
     case NSFetchedResultsChangeType.Delete: 
      // Note that for Delete, we delete the row at __indexPath__ 
      if let deleteIndexPath = indexPath { 
       self.tableView.deleteRowsAtIndexPaths([deleteIndexPath], withRowAnimation: UITableViewRowAnimation.Fade) 
      } 
     case NSFetchedResultsChangeType.Update: 
      // Note that for Update, we update the row at __indexPath__ 
      // Not yet implemented 
      break 
     case NSFetchedResultsChangeType.Move: 
      // Note that for Move, we delete the row at __indexPath__ 
      if let deleteIndexPath = indexPath { 
       self.tableView.deleteRowsAtIndexPaths([deleteIndexPath], withRowAnimation: UITableViewRowAnimation.Fade) 
      } 

      // Note that for Move, we insert a row at the __newIndexPath__ 
      if let insertIndexPath = newIndexPath { 
       self.tableView.insertRowsAtIndexPaths([insertIndexPath], withRowAnimation: UITableViewRowAnimation.Fade) 
      } 
     } 
} 


func controller(
    controller: NSFetchedResultsController, 
    didChangeSection sectionInfo: NSFetchedResultsSectionInfo, 
    atIndex sectionIndex: Int, 
    forChangeType type: NSFetchedResultsChangeType) { 

     switch type { 
     case .Insert: 
      // AAAAAAAAAA 
      let sectionIndexSet = NSIndexSet(index: sectionIndex) 
      self.tableView.insertSections(sectionIndexSet, withRowAnimation: UITableViewRowAnimation.Fade) 
      // BBBBBBBBBBB 
      // break 
     case .Delete: 
      let sectionIndexSet = NSIndexSet(index: sectionIndex) 
      self.tableView.deleteSections(sectionIndexSet, withRowAnimation: UITableViewRowAnimation.Fade) 
     default: 
      break 
     } 
} 

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

Примечание: если я закомментируйте строки под AAAAAAAAAA и раскомментируйте в BBBBBBBBBB, я могу видеть клетки появляются очень кратко, но каждая ячейка ниже этой вставленной клетки исчезает, и я получаю эту ошибку, а не много раз:

no index path for table cell being reused

Любая помощь/предложение оценены!

ответ

0

Ну, я узнал, что:

«Одна из самых больших проблем, с NSFetchedResultsController является то, что он не может показать пустые секции.»

Это упоминалось в this blog post, в котором упоминается способ обойти его (Примечание: я еще не реализовал это, но теперь я знаю, что это невозможно интуитивно).

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