TLDR - 我的FRC似乎与它所链接的表格视图不同步。我怎样才能让它同步?
My View Controller(VC)有一个名为holesTable
的表视图,由名为fetchedResultsController
的获取结果控制器(FRC)管理。
当用户按下VC上的保存按钮时,它会调用名为IBAction
的{{1}}。这将数据保存在FRC的托管对象上下文中,然后测试是否已遵循所有数据规则。捕获任何错误并将消息发送到另一个VC,该VC在展开后向用户显示错误(此处未显示)。
我发现FRC与屏幕SaveHoles
的内容不同,因为函数holesTable
在调用时没有发现任何错误。但是,我能够验证底层数据库是否已接收并存储了屏幕上的数据。
对VC的后续调用将显示已保存的数据,随后按下“保存”按钮将找到错误问题。
因此,在我进行验证时,我的FRC结果似乎与lookForSIProblems
中显示的结果不同步。
这是重要的代码:
holesTable
编辑#1 -
在回应@AgRizzo的评论时,完整的FRC代表方法如下所示。
这些似乎运作良好,是我在我的应用程序中使用过的代理代码的副本。
fileprivate lazy var fetchedResultsController: NSFetchedResultsController<Hole> = {
// Create Fetch Request
let fetchRequest: NSFetchRequest<Hole> = Hole.fetchRequest()
// Configure Fetch Request
self.teeColourString = self.scorecard?.value(forKey: "teeColour") as! String?
fetchRequest.predicate = NSPredicate(format: "%K == %@ AND %K == %@", "appearsOn.offeredAt.name", self.courseName!, "appearsOn.teeColour", self.teeColourString!)
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "holeNumber", ascending: true)]
// Create Fetched Results Controller
let fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: self.coreDataManager.mainManagedObjectContext, sectionNameKeyPath: nil, cacheName: nil)
// Configure Fetched Results Controller
fetchedResultsController.delegate = self
return fetchedResultsController
}()
@IBAction func saveHoles(_ sender: Any) {
print("Prepare to save")
do {
try fetchedResultsController.managedObjectContext.save()
}
catch let error as NSError {
print("Could not save. \(error), \(error.userInfo)")
}
lookForSIProblems(holes: fetchedResultsController.fetchedObjects!)
}
func lookForSIProblems(holes: [Hole]) {
// Takes a fetched result set of 18 records and looks for duplicate or missing SI values
// It should not be possible to have duplicate hole numbers, so the check is done to see if the SI number has already been seen before and, if so, for which other hole.
var SIexists: [Bool] = [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false]
var SIToCheck: Int
let maxHole = 18
var currentHole = 0
var proceed = true
while currentHole < maxHole && proceed {
SIToCheck = Int(holes[currentHole].strokeIndex)
if SIToCheck == 0 {
// This can only happen when the scorecard has not been completed
messagesToPassBack = ["Incomplete Scorecard", "Not all holes have been given a valid Stroke Index. Your changes have been saved but you cannot enter player scores until this error has been fixed."]
flagIncompleteParForCourse(errorCode: 0)
proceed = false
} else if !SIexists[SIToCheck-1] {
// No SI for this hole number has yet appeared, so set it and carry on
SIexists[SIToCheck-1] = true
currentHole += 1
} else {
// This SI has already been seen
messagesToPassBack = ["Duplicate Stroke Index", "Stroke Index \(SIToCheck) has been duplicated. Your changes have been saved but you cannot enter player scores until this error has been fixed."]
flagIncompleteParForCourse(errorCode: 1)
proceed = false
}
}
}
编辑#2:
为了查看FRC是否在每次编辑时都进行了更新,我将extension ScorecardViewController: NSFetchedResultsControllerDelegate {
func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
holesTable.beginUpdates()
}
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
holesTable.endUpdates()
}
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
switch type {
case .update:
holesTable.reloadRows(at: [indexPath!], with: .automatic)
case .insert:
holesTable.insertRows(at: [newIndexPath!], with: .automatic)
case .delete:
holesTable.deleteRows(at: [indexPath!], with: .automatic)
case .move:
holesTable.moveRow(at: indexPath! as IndexPath, to: newIndexPath! as IndexPath)
}
}
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange sectionInfo: NSFetchedResultsSectionInfo, atSectionIndex sectionIndex: Int, for type: NSFetchedResultsChangeType) {
switch type {
case .insert:
holesTable.insertSections(NSIndexSet(index: sectionIndex) as IndexSet, with: .fade)
case .delete:
holesTable.deleteSections(NSIndexSet(index: sectionIndex) as IndexSet, with: .fade)
case .move:
break
case .update:
break
}
}
}
的调用添加到了FRC委托方法中:
lookForSIProblems
结果是FRC 显示与表同步的值。我继续孤立我认为问题所在。如果我在表中编辑一个获取的对象,然后立即点击“保存”按钮,func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
switch type {
case .update:
holesTable.reloadRows(at: [indexPath!], with: .automatic)
lookForSIProblems(fetchedResultsController.fetchedObjects!)
case .insert:
holesTable.insertRows(at: [newIndexPath!], with: .automatic)
case .delete:
holesTable.deleteRows(at: [indexPath!], with: .automatic)
case .move:
holesTable.moveRow(at: indexPath! as IndexPath, to: newIndexPath! as IndexPath)
}
}
中的FRC似乎正在使用“脏”数据。但是,如果我在表格中编辑对象但是点击表格中的其他项目,那么lookForSIProblems
中的FRC会使用“新鲜”数据。
不确定这意味着什么。