ios - 删除后重新加载应用程序时, TableView 中的核心数据条目会出现

标签 ios swift xcode tableview

所以我想删除我的 TableView 中的条目。我目前正在使用核心数据。当我删除我的应用程序中的条目时,会发生什么情况,它似乎已被删除,但当我重新加载应用程序时,该条目会重新出现。这很可能是因为我没有删除 coredata 本身的条目,只有在有意义的情况下才在 tableview 中删除它。

我遵循了多个关于如何实现 TableView Controller 来处理包括删除在内的更改的指南。这就是为什么我对为什么我的代码不起作用感到困惑。

我的 View Controller :

import UIKit
import CoreData

class ViewController: UITableViewController, NSFetchedResultsControllerDelegate {

    let cellId = "cellId"

    fileprivate lazy var fetchedResultsController: NSFetchedResultsController<AlarmItem> = {
        //create fetch request
        let fetchRequest: NSFetchRequest<AlarmItem> = AlarmItem.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)

        let managedObjectContext = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext

        fetchedResultsController.delegate = self

        return fetchedResultsController
    }()

    func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
        tableView.beginUpdates()
    }

    func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
        tableView.endUpdates()
    }

    func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {

        switch(type) {
        case .insert:
            if let indexPath = newIndexPath {
                tableView.insertRows(at: [indexPath], with: .fade)
            }
            break;
        case .delete:
            if let indexPath = indexPath {
                tableView.deleteRows(at: [indexPath], with: .fade)
            }
            break;
        case .update:
            //this is mostlikely where the problem lies
            //self.tableView.reloadData()
            if let indexPath = indexPath, let cell = tableView.cellForRow(at: indexPath) {
                configureCell(cell, at: indexPath)
            }
            break;
        case .move:
            if let indexPath = indexPath {
                tableView.deleteRows(at: [indexPath], with: .fade)
            }
            if let newIndexPath = newIndexPath {
                tableView.insertRows(at: [newIndexPath], with: .fade)
            }
            break;
        @unknown default:
            print("Something odd is happening")
        }
    }


    override func viewDidLoad() {
        super.viewDidLoad()

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        do {
            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"
        }

        //work on fullscreen display
        //this does not work
        //alertController.modalPresentationStyle = UIModalPresentationStyle.overFullScreen
        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: "AlarmItem", in: managedContext)!
        let item = NSManagedObject(entity: entity, insertInto: managedContext)
        item.setValue(itemName, forKey: "alarmAttributes")

        do {
            try managedContext.save()
            tableView.reloadData()

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


    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
        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) as NSManagedObject
        cell.textLabel?.text = alarmItem.value(forKeyPath: "alarmAttributes") as? String
        return cell
    }

    func tableView(_ tableView: UITableView!, canEditRowAtIndexPath indexPath: NSIndexPath!) -> Bool {
        return true
    }

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
    }

    override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
        guard editingStyle == .delete else { return }

        //fetch
        let toBeDeleted = fetchedResultsController.object(at: indexPath)

        //delete
        fetchedResultsController.managedObjectContext.delete(toBeDeleted)
    }

    func tableView(_tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "AlarmItem", for: indexPath)
        configureCell(cell, at: indexPath)

        return cell
    }

    func configureCell(_ cell: UITableViewCell, at indexPath: IndexPath) {
        let alarmItem = fetchedResultsController.object(at: indexPath)

        //configure cell
        cell.textLabel?.text = alarmItem.value(forKeyPath: "alarmAttributes") as? String
    }
}

最佳答案

请补充:

fetchedResultsController.managedObjectContext.save()

作为函数的最后一行:

func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath)

关于ios - 删除后重新加载应用程序时, TableView 中的核心数据条目会出现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56698237/

相关文章:

ios - 如何更改 MFMessageComposeViewController 的导航栏颜色?

iphone - 在 iPhone 中下载和查看 PDF

ios - 如何获取 TableView 中的特定单元格

iOS 低功耗蓝牙 : unable to connect using stored pairing data

ios - Xcode 6.1 构建在设备上崩溃

ios - 禁用 iPhone 而非 iPad 的旋转

ios - iOS 上的 Cordova 应用程序中的 Iframe Youtube 视频不再工作

ios - 球从墙上弹起不起作用

ios - 如何在 UITextField 周围添加可点击标签

xcode - 应用内截图并附加到电子邮件,无需保存到库中