由于未捕获的异常“NSInvalidArgumentException”,我的 Xcode 应用程序在尝试实现 NSFetchedResultsController 后崩溃

Posted

技术标签:

【中文标题】由于未捕获的异常“NSInvalidArgumentException”,我的 Xcode 应用程序在尝试实现 NSFetchedResultsController 后崩溃【英文标题】:My Xcode App crashes after trying to implement NSFetchedResultsController due to uncaught exception 'NSInvalidArgumentException' 【发布时间】:2019-06-19 06:59:39 【问题描述】:

我最近问了一个关于如何为我的 CoreData 实体实现删除功能的问题。 (这里:How do I delete CoreData entries in a tableview that uses a persistentcontainer?)我被告知我应该使用 NSFetchResultsController,所以我开始研究它。我以为我做对了,现在我的代码在运行后立即崩溃。

我尝试使用教程来实现 FetchedResultsController。我很确定我已正确执行所有步骤以在我的应用程序中实施,但它仍然崩溃。下面提供了我的尝试。我的原始代码在上面的段落中。

ViewController.swift

import UIKit
import CoreData

class ViewController: UITableViewController 

    //var alarmItems: [NSManagedObject] = []
    let cellId = "cellId"

    private let persistentContainer = NSPersistentContainer(name: "AlarmItems")

    fileprivate lazy var fetchedResultsController: NSFetchedResultsController<AlarmItems> = 
        //create fetch request
        let fetchRequest: NSFetchRequest<AlarmItems> = AlarmItems.fetchRequest()

        //configure fetch request
        //fetchRequest.sortDescriptors = [NSSortDescriptor(key: )]

        let fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: self.persistentContainer.viewContext, sectionNameKeyPath: nil, cacheName: nil)

        fetchedResultsController.delegate = self as? NSFetchedResultsControllerDelegate

        return fetchedResultsController
    ()


    override func viewDidLoad() 
        super.viewDidLoad()


    override func viewWillAppear(_ animated: Bool) 
        super.viewWillAppear(animated)
        //guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else  return 
        //let managedContext = appDelegate.persistentContainer.viewContext
        //let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "AlarmItems")
        do 
            //alarmItems = try managedContext.fetch(fetchRequest)
            try fetchedResultsController.performFetch()
         catch let err as NSError 
            print("Failed to fetch items", err)
        
    

    @objc func addAlarmItem(_ sender: AnyObject) 
        //print("this works")
        let alertController = UIAlertController(title: "Add New Item", message: "Please fill in the blanks", preferredStyle: .alert)
        let saveAction = UIAlertAction(title: "Save", style: .default)  [unowned self] action in

            //combined string of attributes
            let myStrings: [String] = alertController.textFields!.compactMap  $0.text 
            let myText = myStrings.joined(separator: ", ")

            self.save(myText)
            self.tableView.reloadData()
        
        let cancelAction = UIAlertAction(title: "Cancel", style: .destructive, handler: nil)

        alertController.addTextField  (textField) in
            textField.placeholder = "Enter Name of Engineer"
        
        alertController.addTextField  (textField) in
            textField.placeholder = "Enter Date of Alarm in DD/MM/YYYY"
        
        alertController.addTextField  (textField) in
            textField.placeholder = "Enter Time of Alarm in 24h (eg: 2300)"
        
        alertController.addTextField  (textField) in
            textField.placeholder = "Please indicate True/False (type True or False)"
        
        alertController.addTextField  (textField) in
            textField.placeholder = "Insert comments (if any), or NIL"
        


        alertController.addAction(saveAction)
        alertController.addAction(cancelAction)
        present(alertController, animated: true, completion: nil)
    

    func save(_ itemName: String) 
        guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else  return 
        let managedContext = appDelegate.persistentContainer.viewContext
        let entity = NSEntityDescription.entity(forEntityName: "AlarmItems", in: managedContext)!
        let item = NSManagedObject(entity: entity, insertInto: managedContext)
        item.setValue(itemName, forKey: "alarmAttributes")


        do 
            try managedContext.save()
            //NSFetchedResultsController.append(item)
            tableView.reloadData()

         catch let err as NSError 
            print("Failed to save an item", err)
        
    

    @objc func exportCSV(_ sender: AnyObject) 
        //will work on exporting csv in the future
        return
    
    override func numberOfSections(in tableView: UITableView) -> Int 
        return fetchedResultsController.sections?.count ?? 0
    

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
        //return alarmItems.count
        let sectionInfo = fetchedResultsController.sections![section]
        return sectionInfo.numberOfObjects
    

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath)
        let alarmItem = fetchedResultsController.object(at: indexPath)
        cell.textLabel?.text = alarmItem.value(forKeyPath: "alarmAttributes") as? String
        return cell
    



错误是:

由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“NSFetchedResultsController 的实例需要非零的 fetchRequest 和 managedObjectContext”

他们还说即使我的代码中已经有获取请求功能,它也无法加载名为 AlarmItems 的模型。

【问题讨论】:

尝试添加异常断点,看看你的代码哪里出错了。它会给你一个想法,你需要检查你的代码。 【参考方案1】:

首先删除let persistentContainer = NSPersistentContainer(name: "AlarmItems")并从AppDelegate获取上下文

错误不完整

NSFetchedResultsController 的一个实例需要一个非零的 fetchRequest带有排序描述符和 managedObjectContext

fileprivate lazy var fetchedResultsController: NSFetchedResultsController<AlarmItems> = 
    //create fetch request
    let fetchRequest: NSFetchRequest<AlarmItems> = AlarmItems.fetchRequest()

    //configure fetch request
    fetchRequest.sortDescriptors = [NSSortDescriptor(key: "alarmAttributes", ascending: true)]
    let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext

    let fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)

    fetchedResultsController.delegate = self

    return fetchedResultsController
()

如前所述,请将NSManagedObject 子类命名为单数形式AlarmItem

【讨论】:

非常感谢您在过去几天的帮助:) 我真的很感激。我会试试的,希望一切都会好起来的

以上是关于由于未捕获的异常“NSInvalidArgumentException”,我的 Xcode 应用程序在尝试实现 NSFetchedResultsController 后崩溃的主要内容,如果未能解决你的问题,请参考以下文章

由于未捕获的异常而终止应用程序 [UIImageView _isResizable]

由于未捕获的异常而终止应用程序,同时加载视图

由于未捕获的异常“NSInternalInconsistencyException”错误而终止应用程序

“由于未捕获的异常而终止应用程序”在推送视图控制器时崩溃

由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,

由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序