尝试使用 coredata 保存待办事项列表不保存

Posted

技术标签:

【中文标题】尝试使用 coredata 保存待办事项列表不保存【英文标题】:Attempting to save todo list using coredata doesnt save 【发布时间】:2019-06-18 19:32:22 【问题描述】:

我已经设置了一个 tableview 控制器,并将它用于带有 coredata 的重量跟踪列表,以保存所有的条目。虽然在应用程序打开时添加条目并显示它们,但在下一次应用程序加载时它不会显示这些条目。我很感谢您的帮助,因为我对 swift 编码相对较新。

data model screenshot

import UIKit
import CoreData

class TodoViewController: UITableViewController 

    var items = [Items]()

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

    var selectedCategory: Items?
        didSet
            loadItems()
        
    

    override func viewDidLoad() 
        super.viewDidLoad()
    

    //MARK: Table View Datasource Methods
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        return items.count
    

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        let cell = tableView.dequeueReusableCell(withIdentifier: "Item", for: indexPath)
        let item = items[indexPath.row]
        cell.textLabel?.text = item.name
        cell.accessoryType = item.completed ? .checkmark : .none
        return cell
    

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) 
        tableView.deselectRow(at: indexPath, animated: true)
        items[indexPath.row].completed = !items[indexPath.row].completed
        saveItems()
    

    override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool 
        return true
    

    override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) 
        if (editingStyle == .delete)
            let item = items[indexPath.row]
            items.remove(at: indexPath.row)
            context.delete(item)

            do
                try context.save()
            catch
                print("Error deleting item with \(error)")
            
            tableView.deleteRows(at: [indexPath], with: .automatic)
        
    

    @IBAction func addButtonPressed(_ sender: UIBarButtonItem) 
        var textField = UITextField()
        let alert = UIAlertController(title: "Add New Weight", message: "", preferredStyle: .alert)
        let action = UIAlertAction(title: "Save", style: .default)  (action) in

            let newItem = Items(context: self.context)
            newItem.name = textField.text!
            self.items.append(newItem)
            self.saveItems()
        
        alert.addAction(action)
        alert.addTextField  (field) in
            textField = field
            textField.placeholder = "Add Weight"
        
        present(alert, animated: true, completion: nil)

    func saveItems()
        do
            try context.save()
        catch
            print("Error Saving item with \(error)")
        
        self.tableView.reloadData()
    

    func loadItems()
        let request: NSFetchRequest<Items> = Items.fetchRequest()

        do
            items = try context.fetch(request)
        catch
            print("Error fetching data from context \(error)")
        
        tableView.reloadData()
    


【问题讨论】:

【参考方案1】:

将你的 items 数组更新为 NSManagedObject

var items: [NSManagedObject] = []

使用此方法进行保存并从保存操作中调用它:

func save(name: String, completed: Bool) 
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else 
  return


let managedContext = appDelegate.persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "Items", in: managedContext)!
let item = NSManagedObject(entity: entity, insertInto: managedContext)
item.setValue(name, forKeyPath: "name")
item.setValue(completed, forKeyPath: "completed")

do 
  try managedContext.save()
  items.append(item)
 catch let error as NSError 
  print("Could not save. \(error), \(error.userInfo)")


对于加载项目,请使用以下方法:

func loadItems() 
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else 
  return


let managedContext = appDelegate.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Items")

do 
  items = try managedContext.fetch(fetchRequest)
 catch let error as NSError 
  print("Could not fetch. \(error), \(error.userInfo)")


然后将 cellForRowAtIndexPath 方法更新为:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let cell = tableView.dequeueReusableCell(withIdentifier: "Item", for: indexPath)
    let item = items[indexPath.row]
    cell.textLabel?.text = item.value(forKeyPath: "name") as? String
    cell.accessoryType = item.value(forKeyPath: "completed") as? Bool ? .checkmark : .none
    return cell

使用 KVC 访问数组项中的任何属性,如下所示:

item.value(forKeyPath: "name") as? String

【讨论】:

以上是关于尝试使用 coredata 保存待办事项列表不保存的主要内容,如果未能解决你的问题,请参考以下文章

CoreData 不将数据保存到数据库

jQuery模仿ToDoList实现简单的待办事项列表

在 Xcode 中使用 CoreData 从模态视图控制器重新加载视图

如何在内部保存数据?

如何在应用程序中保存数据?

无法从 Listview 中删除项目(待办事项列表),长按没有任何反应