【问题标题】:How do I delete CoreData entries in a tableview that uses a persistentcontainer?如何删除使用持久化容器的表视图中的 CoreData 条目?
【发布时间】:2019-10-31 17:17:04
【问题描述】:

我正在设计一个应用程序,用户将在其中使用多个文本字段在警报视图中键入信息。然后将这些字符串组合并保存在实体的属性中(作为一个实体)。然后这将显示在表格视图中。

现在,如果用户输入错误,我将实现一种删除条目的方法。

我见过很多他们说使用以下代码删除CoreData中的条目的地方:

override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath)
{
    let managedObjectContext = coreData.persistentContainer.viewContext

    if editingStyle == .delete
    {
        movieToDelete = fetchedResultController.object(at: indexPath)

        let confirmDeleteAlertController = UIAlertController(title: "Remove Movie", message: "Are you sure you would like to delete \"\(movieToDelete!.title!)\" from your movie library?", preferredStyle: UIAlertControllerStyle.actionSheet)

        let deleteAction = UIAlertAction(title: "Delete", style: UIAlertActionStyle.default, handler: { [weak self] (action: UIAlertAction) -> Void in
            managedObjectContext.delete((self?.movieToDelete!)!)
            self?.coreData.saveContext()
            self?.movieToDelete = nil
        })

        let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel, handler: { [weak self] (action: UIAlertAction) -> Void in
            self?.movieToDelete = nil
        })

        confirmDeleteAlertController.addAction(deleteAction)
        confirmDeleteAlertController.addAction(cancelAction)

        present(confirmDeleteAlertController, animated: true, completion: nil)

    }
}

但是,我正在关注 youtube 上的教程,因此我的代码中没有 ManagedObjectContext 来使用 editingStyle.delete。现在我对如何删除条目感到困惑。我是否要更改我之前的代码以支持ManagedObjectContext,或者有没有办法通过持久容器删除条目?

这是我viewController 中的代码,我认为这对手头的问题很重要:

class ViewController: UITableViewController {

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


    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)
        } 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()
            alarmItems.append(item)

        } 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 tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
        return alarmItems.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath)
        let alarmItem = alarmItems[indexPath.row]
        cell.textLabel?.text = alarmItem.value(forKeyPath: "alarmAttributes") as? String
        return cell
    }

    /*
    //create delete feature

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


        }
    }
 */

}

【问题讨论】:

  • 您的问题不清楚,因为您询问是否应该“支持 ManagedObjectContextor”,但您的代码已经使用了 NSManagedObjectContext 对象,这当然不足为奇,因为此类是核心数据中最核心的类之一.
  • 我试图做 managedContext.delete 但这没有用,因为 xcode 无法识别 managedContext 是什么(它是我的 NSManagedObjectContext)所以我认为我的代码或我如何调用可能有错误上下文。我是否必须在我的新函数中声明一个新的 managedobjectcontext 才能删除条目?
  • 嘿,请检查这个网址:- stackoverflow.com/a/38018674/8201581.

标签: ios arrays swift uitableview core-data


【解决方案1】:

当你使用NSFetchedResultsController删除数据源数组

罢工>

var alarmItems: [NSManagedObject] = []  

以及所有其他出现的alarmItemsNSFetchedResultsController 实例成为数据源数组

viewWillAppear 中重新获取数据

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    do {
        try fetchedResultsController.performFetch()
        tableView.reloadData()
    } catch {
        print(error)
    }
}

替换数据源和委托方法
override func numberOfSections(in tableView: UITableView) -> Int {
    return fetchedResultsController.sections?.count ?? 0
}

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
}

现在你的删除方法应该可以工作了。

注意:

我们鼓励您始终使用 NSManagedObject 子类 AlarmItems(顺便说一下,每个 Core Data 记录在语义上代表一个 AlarmItem)和点符号,例如

let alarmItem = fetchedResultsController.object(at: indexPath) as! AlarmItem
cell.textLabel?.text = alarmItem.alarmAttributes

【讨论】:

  • 啊!所以基本上,我能做的就是删除所有的 alarmItems 实例并用 NSFetchedResultsController 替换它,因为控制器已经充当 CoreData 实体?非常感谢您的帮助,我会试试看!
  • 请阅读NSFetchedResultsController documentationhere是如何使用NSFetchedResultsController的教程
  • 我试图实现你告诉我的(非常感谢你),但现在我的应用程序崩溃了。我很快会问另一个问题。
猜你喜欢
  • 2017-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多