数据库中以段标题的一条记录填充数据库,它与多(UserInstruction)到一个(SectionHeading)关系,“ fetchedResultsController.sections”返回nil

致命错误:未正确配置FRC:文件/Users/tae/Documents/Assignments/BrickMatcherV5/BrickMatcherV5/Controllers/InformationViewController.swift,第101行
2019-12-18 18:18:18.406622 + 0000 BrickMatcherV5 [3924:121317]致命错误:未正确配置FRC:文件/Users/tae/Documents/Assignments/BrickMatcherV5/BrickMatcherV5/Controllers/InformationViewController.swift,第101行

import UIKit
import CoreData

class InformationViewController: UITableViewController {

    let cellId = "sdlfjowieurewfn34898442249sd;ds;lfkds;f47824dslaksjfs;ad"

    var model: UserInstructionsModel!
    let defaults = UserDefaults.standard
    var networkManager = NetworkManager.shared
    var instructionURLComponents = URLComponents()

    // Create a reference to the CoreData Stack
    private let cdStack = CoreDataStack.shared

    // The all mighty FetchedResultsController
    fileprivate lazy var fetchedResultsController: NSFetchedResultsController <UserInstruction> = {

        let fetchRequest:NSFetchRequest =  UserInstruction.fetchRequest()
        fetchRequest.sortDescriptors = [NSSortDescriptor(key: "sectionHeading.name", ascending: true),
        NSSortDescriptor(key: "rowOrder", ascending: true)]

        //managedObjectContext is your instance of NSManagedObjectContext
        let fetchedResultsContoller = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: CoreDataStack.shared.mainContext, sectionNameKeyPath: "sectionHeading.name", cacheName: nil)
        fetchedResultsContoller.delegate = self
        return fetchedResultsContoller
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        navigationItem.title = "How To Use"
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellId)
        tableView.register(SubtitleTableViewCell.self, forCellReuseIdentifier: cellId)
        tableView.tableFooterView = UIView(frame: CGRect.zero)
        model = UserInstructionsModel(coreDataStack: CoreDataStack.shared)
        fetchHelpInstructions()

        do {
            try fetchedResultsController.performFetch()
            print("try done")
        } catch let fetchError {
            print("Fetch Error: \(fetchError.localizedDescription)")
        }

        // Set the Show Help Screen Switch
        self.defaults.set(true, forKey: "seenHelpInformation")
    }

    private func fetchHelpInstructions() {

        let seenHelpInformation = self.defaults.bool(forKey: "seenHelpInformation")

        if seenHelpInformation == false {

            instructionURLComponents.scheme = ProcessingServer.scheme
            instructionURLComponents.host = ProcessingServer.host
            instructionURLComponents.port = ProcessingServer.port
            instructionURLComponents.path = EndPoints.instructions
            networkManager.fetchInstructions(url: instructionURLComponents.url!, completion: { Instruction in

                guard let serverInstructions = Instruction else { return }

                do {
                    try self.model.saveInstructions(instructions: serverInstructions)
                } catch {

                    let alertController = UIAlertController(title: "Error Saving Instructions", message: error as? String, preferredStyle: .alert)
                    let OKAction = UIAlertAction(title: "OK", style: .default) { action in
                        print("Pressed OK")
                    }
                    alertController.addAction(OKAction)
                    self.present(alertController, animated: true, completion: nil)
                }
            })
        }
    }
}


extension InformationViewController {

    // MARK: - Table view data source
    override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {

        guard let sections = fetchedResultsController.sections else { fatalError("No Sections") }

        let sectionInformation = sections[section]
        return sectionInformation.name
    }

    override func numberOfSections(in tableView: UITableView) -> Int {

        guard let sections = fetchedResultsController.sections else { fatalError("FRC not configuired correctly") }
        return sections.count
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        guard let sections = fetchedResultsController.sections else { fatalError("FRC not configuired correctly") }

        let sectionInformation = sections[section]
        return sectionInformation.numberOfObjects
    }


    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath)

        let instruction = fetchedResultsController.object(at: indexPath)

        cell.textLabel?.text = instruction.headlineDisplayText
        cell.detailTextLabel?.text = instruction.descriptionDisplayText

        return cell
    }

    class SubtitleTableViewCell: UITableViewCell {

        override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
            super.init(style: .subtitle, reuseIdentifier: reuseIdentifier)
        }

        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    }
}

extension InformationViewController : NSFetchedResultsControllerDelegate {

func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, sectionIndexTitleForSectionName sectionName: String) -> String? {
    return String(sectionName.hashValue)
}
}


型号详情

swift - 快速编程的核心数据fetchedResultsController.sections无错误-LMLPHP

swift - 快速编程的核心数据fetchedResultsController.sections无错误-LMLPHP

最佳答案

为了正确显示这些部分,您必须在与sectionNameKeyPath对应的第一个位置指定一个排序描述符

fetchRequest.sortDescriptors = [NSSortDescriptor(key: "sectionHeading.name", ascending: true),
                                NSSortDescriptor(key: "rowOrder", ascending: true)]


并将numberOfSections替换为

override func numberOfSections(in tableView: UITableView) -> Int {
    return fetchedResultsController.sections?.count ?? 0
}


那么您可以强制解开所有出现的fetchedResultsController.sections,因为如果numberOfSections返回0,则不会调用所有其他数据源方法。

10-08 12:15