在一个TableView中使用2个FRC并configurationFRCDelegate

我发现这个post的问题链接 ,我已经尽我所能将它从Obj-C转换为Swift。 当我添加一个新的实体,并尝试将其保存到CoreData,该应用程序崩溃,并突出显示这一行:

modifiedIndexPath = NSIndexPath(row: (indexPath?.row)!, section: 0) 

后面的绿色错误如下: Thread 1; EXC_BREAKPOINT (code=1, subcode=0x100008b118) Thread 1; EXC_BREAKPOINT (code=1, subcode=0x100008b118) 。 我不知道这是什么意思,输出面板也只显示(llbd)绿色。

编辑 – 我发现应用程序崩溃,因为indexPath?.row返回零。 我只是不知道为什么它返回零。

我的VC有两个部分是这样设置的:

  func numberOfSections(in tableView: UITableView) -> Int { return 2 } 

标题的标题是这样设置的:

 // set the titles of the tables func tableView( _ tableView : UITableView, titleForHeaderInSection section: Int)->String? { switch(section) { case 0: if(positiveFetchedResultsController.fetchedObjects!.count == 0){ return nil } else{ return "Owes you:" } case 1: if(negativeFetchedResultsController.fetchedObjects!.count == 0){ return nil } else{ return "You owe:" } default :return nil } } 

这是我如何创build我的两个RFC

 override func viewWillAppear(_ animated: Bool) { // load the data let fetchRequest: NSFetchRequest<Person> = Person.fetchRequest() fetchRequest.predicate = NSPredicate(format:"statement.@sum.amountOwed >= 0") let sort = NSSortDescriptor(key: #keyPath(Person.name), ascending: true) fetchRequest.sortDescriptors = [sort] positiveFetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: coreDataStack.managedContext, sectionNameKeyPath: nil, cacheName: nil) do{ try positiveFetchedResultsController.performFetch() }catch let error as NSError{ print("Fetching error: \(error), \(error.userInfo)") } let negativFetchRequest: NSFetchRequest<Person> = Person.fetchRequest() negativFetchRequest.predicate = NSPredicate(format:"statement.@sum.amountOwed < 0") let negativeSort = NSSortDescriptor(key: #keyPath(Person.name), ascending: true) negativFetchRequest.sortDescriptors = [negativeSort] negativeFetchedResultsController = NSFetchedResultsController(fetchRequest: negativFetchRequest, managedObjectContext: coreDataStack.managedContext, sectionNameKeyPath: nil, cacheName: nil) do{ try negativeFetchedResultsController.performFetch() }catch let error as NSError{ print("Fetching error: \(error), \(error.userInfo)") } positiveFetchedResultsController.delegate = self negativeFetchedResultsController.delegate = self print("\(positiveFetchedResultsController.fetchedObjects!.count) positive fetch count") //print("\(positiveFetchedResultsController.fetchedObjects![0].statement!.count) positive statements count") print("\(negativeFetchedResultsController.fetchedObjects!.count) negative fetch count") //print("\(negativeFetchedResultsController.fetchedObjects![0].statement!.count) negative statements count") } 

这里是我从上面的post转换来的FRC委托代码:

 extension ViewController: NSFetchedResultsControllerDelegate { func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) { tableView.beginUpdates() } func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) { var modifiedIndexPath = IndexPath() var modifiedNewIndexPath = IndexPath() if(controller == positiveFetchedResultsController){ modifiedIndexPath = IndexPath(row: (indexPath?.row)!, section: 0) modifiedNewIndexPath = IndexPath(row: (newIndexPath?.row)!, section: 0) } if(controller == negativeFetchedResultsController){ modifiedIndexPath = IndexPath(row: (indexPath?.row)!, section: 1) modifiedNewIndexPath = IndexPath(row: (newIndexPath?.row)!, section: 1) } switch type { case .insert: //tableView.insertRows(at: [newIndexPath!], with: .automatic) tableView.insertRows(at: [modifiedNewIndexPath as IndexPath], with: .automatic) case .delete: //tableView.deleteRows(at: [indexPath!], with: .automatic) tableView.deleteRows(at: [modifiedIndexPath as IndexPath], with: .automatic) case .update: tableView.reloadRows(at: [modifiedIndexPath as IndexPath], with: .automatic) case .move: //tableView.deleteRows(at: [indexPath!], with: .automatic) //tableView.insertRows(at: [newIndexPath!], with: .automatic) tableView.deleteRows(at: [modifiedIndexPath as IndexPath], with: .automatic) tableView.insertRows(at: [modifiedNewIndexPath as IndexPath], with: .automatic) } } func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) { tableView.endUpdates() } 

}

编辑似乎IndexPath.row是indexindex和newIndexPath返回零。 我试图阻止这个代码发生这种情况,但是我不知道我是否正在朝这个思维过程的正确方向前进:

  print("\(indexPath?.row) is the index row number") print("\(newIndexPath?.row) is the NEW index row number") if(controller == self.positiveFetchedResultsController){ if(indexPath?.row == nil) { modifiedNewIndexPath = IndexPath(row: 0, section: 0) modifiedNewIndexPath = IndexPath(row: 0, section: 0) } else{ modifiedIndexPath = IndexPath(row: indexPath!.row, section: 0) modifiedNewIndexPath = IndexPath(row: (newIndexPath?.row)!, section: 0) } } if(controller == negativeFetchedResultsController){ if(indexPath?.row == nil) { modifiedIndexPath = IndexPath(row: 0, section: 1) modifiedNewIndexPath = IndexPath(row: 0, section: 1) } else{ modifiedIndexPath = IndexPath(row: indexPath!.row, section: 1) modifiedNewIndexPath = IndexPath(row: (newIndexPath?.row)!, section: 1) } } 

这里是我如何保存我的数据:

 /* STEP 2 - Check to see if that persons names was already used */ let personFetchRequest: NSFetchRequest<Person> = Person.fetchRequest() personFetchRequest.predicate = NSPredicate(format: "name == %@", name.text!) do{ let results = try coreDataStack.managedContext.fetch(personFetchRequest) print("\(results.count) this is the results count for the predicate") guard results.count == 0 else{ // print("The Same Name is Used") warningText = "You already used that name." warningMessage() return } /* STEP 3 - Use the name that was typed in */ print("You can use that name") //let personEntity = NSEntityDescription.entity(forEntityName: "Person", in: coreDataStack.managedContext) let person = Person(entity: Person.entity(), insertInto: coreDataStack.managedContext) person.name = name.text /* STEP 4 - Save the data */ coreDataStack.saveContext() self.dismiss(animated: true, completion: {}); }catch{ print("Error") } 

在这个打印声明之后,它似乎就会崩溃

 print("You can use that name") 

我无法保存到CoreData,我不知道为什么。

编辑这似乎已经解决了我的问题,我仍在testing,但似乎是工作。

 func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) { var modifiedIndexPath = IndexPath() var modifiedNewIndexPath = IndexPath() print("\(indexPath?.row) is the index row number") print("\(newIndexPath?.row) is the NEW index row number") if(controller == self.positiveFetchedResultsController){ if(indexPath?.row == nil) { modifiedNewIndexPath = IndexPath(row: 0, section: 0) modifiedNewIndexPath = IndexPath(row: (newIndexPath?.row)!, section: 0) } else if(newIndexPath?.row == nil){ modifiedIndexPath = IndexPath(row: indexPath!.row, section: 0) modifiedNewIndexPath = IndexPath(row: 0, section: 0) } else{ modifiedIndexPath = IndexPath(row: indexPath!.row, section: 0) modifiedNewIndexPath = IndexPath(row: (newIndexPath?.row)!, section: 0) } } if(controller == negativeFetchedResultsController){ if(indexPath?.row == nil) { modifiedIndexPath = IndexPath(row: 0, section: 1) modifiedNewIndexPath = IndexPath(row: (newIndexPath?.row)!, section: 1) } else if(newIndexPath?.row == nil) { modifiedIndexPath = IndexPath(row: indexPath!.row, section: 1) modifiedNewIndexPath = IndexPath(row: 0, section: 1) } else{ modifiedIndexPath = IndexPath(row: indexPath!.row, section: 1) modifiedNewIndexPath = IndexPath(row: (newIndexPath?.row)!, section: 1) } } print("\(indexPath?.row) is the index row number") print("\(newIndexPath?.row) is the NEW index row number") switch type { case .insert: print("\(newIndexPath?.row) is the NEW index row number") // tableView.insertRows(at: [newIndexPath!], with: .automatic) tableView.insertRows(at: [modifiedNewIndexPath as IndexPath], with: .automatic) case .delete: //tableView.deleteRows(at: [indexPath!], with: .automatic) tableView.deleteRows(at: [modifiedIndexPath as IndexPath], with: .automatic) case .update: tableView.reloadRows(at: [modifiedIndexPath as IndexPath], with: .automatic) case .move: //tableView.deleteRows(at: [indexPath!], with: .automatic) //tableView.insertRows(at: [newIndexPath!], with: .automatic) tableView.deleteRows(at: [modifiedIndexPath as IndexPath], with: .automatic) tableView.insertRows(at: [modifiedNewIndexPath as IndexPath], with: .automatic) } } 

看起来像这样的事情的if / else语句的分配。 希望有人可能有一个更清洁的版本。