Мое приложение Xcode падает после попытки реализовать NSFetchedResultsController из-за необработанного исключения «NSInvalidArgumentException» - PullRequest
0 голосов
/ 19 июня 2019

Недавно я задал вопрос о том, как реализовать функцию удаления для моих сущностей CoreData.(здесь: Как удалить записи CoreData в табличном представлении, которое использует 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 Ответ

1 голос
/ 19 июня 2019

Прежде всего удалите let persistentContainer = NSPersistentContainer(name: "AlarmItems") и получите контекст из AppDelegate

Ошибка неполная

Для экземпляра NSFetchedResultsController требуется не nil 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...