如何持久化 tableview 行?

Posted

技术标签:

【中文标题】如何持久化 tableview 行?【英文标题】:How to persist tableview rows? 【发布时间】:2018-05-04 18:02:09 【问题描述】:

我正在创建一个 ios 应用程序,它将每天向我显示一组用户特定的任务,我单击删除以显示其已完成。我将任务保存在核心数据中,然后单击删除 tableview 行。我不会按照用户定义的方式删除 coredata 中的数据,并且需要每天重新加载它。如果应用程序在新的一天打开,我使用 newDay() 函数来决定从 coredata 加载数据。我应该怎么做才能记住当天完成的所有任务?我是否需要创建另一个实体来记住所有任务已完成,还是有更简单的方法?

var tasks: [NSManagedObject] = []
let defaults = UserDefaults.standard
var calender = Calendar.current

override func viewDidLoad() 
    super.viewDidLoad()

    title = "DailyTasker"
    navigationItem.leftBarButtonItem = editButtonItem



override func viewWillAppear(_ animated: Bool) 
    super.viewWillAppear(animated)

    let checkDate = newDay()
    if checkDate

    //1
    guard let appDelegate =
        UIApplication.shared.delegate as? AppDelegate else 
            return
    

    let managedContext =
        appDelegate.persistentContainer.viewContext

    //2
    let fetchRequest =
        NSFetchRequest<NSManagedObject>(entityName: "Task")

    //3
    do 
        tasks = try managedContext.fetch(fetchRequest)
        defaults.set(Date(), forKey: "LastRun")
     catch let error as NSError 
        print("Could not fetch. \(error), \(error.userInfo)")
    
    


func newDay() -> Bool
    if let lastRun = defaults.object(forKey: "LastRun") as? Date
        if !calender.isDateInToday(lastRun)
            return true
         else 
            return false
        
     else 
        return true
    




@IBAction func addName(_ sender: UIBarButtonItem) 
    let alert = UIAlertController(title: "New Task",
                                  message: "Add a new task",
                                  preferredStyle: .alert)

    let saveAction = UIAlertAction(title: "Save",
                                   style: .default) 
                                    [unowned self] action in

                                    guard let textField = alert.textFields?.first,
                                        let nameToSave = textField.text else 
                                            return
                                    

                                    self.save(name: nameToSave)
                                    self.tableView.reloadData()
    

    let cancelAction = UIAlertAction(title: "Cancel",
                                     style: .default)

    alert.addTextField()

    alert.addAction(saveAction)
    alert.addAction(cancelAction)

    present(alert, animated: true)


func save(name: String) 

    guard let appDelegate =
        UIApplication.shared.delegate as? AppDelegate else 
            return
    

    // 1
    let managedContext =
        appDelegate.persistentContainer.viewContext

    // 2
    let entity =
        NSEntityDescription.entity(forEntityName: "Task",
                                   in: managedContext)!

    let task = NSManagedObject(entity: entity,
                               insertInto: managedContext)

    // 3
    task.setValue(name, forKeyPath: "name")

    // 4
    do 
        try managedContext.save()
        tasks.append(task)
     catch let error as NSError 
        print("Could not save. \(error), \(error.userInfo)")
    



// MARK: - Table view data source

override func numberOfSections(in tableView: UITableView) -> Int 
    // #warning Incomplete implementation, return the number of sections
    return 1


override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    // #warning Incomplete implementation, return the number of rows
    return tasks.count



override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let task = tasks[indexPath.row]
    let cell = tableView.dequeueReusableCell(withIdentifier: "TaskerCell", for: indexPath)
    cell.textLabel?.text = task.value(forKeyPath: "name") as? String

    return cell
       

 // Override to support editing the table view.
 override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) 
 if editingStyle == .delete 
 // Delete the row from the data source
 tasks.remove(at: indexPath.row)
 tableView.deleteRows(at: [indexPath], with: .fade)
  else if editingStyle == .insert 

 
 

 override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) 
    tasks.remove(at: indexPath.row)
    tableView.deleteRows(at: [indexPath], with: .fade)
    

【问题讨论】:

【参考方案1】:

您可以为您的任务添加一个日期属性并将其命名为lastDone,例如。然后,您将其设置为任务完成时的当前日期时间,并在获取任务实例时使用谓词,以便您仅获取今天未完成的那些。

 task.lastDone = Date()

我不确定您如何定义“今天”,但 this question 应该可以帮助您创建一个谓词来正确过滤您的任务,尽管您可能还希望包含 lastDone 为空的任务。

【讨论】:

【参考方案2】:

我不确定为什么不能删除数据。是不是因为规格。 如果没有,那么当您将任务保存在 coredata 中时,只需为其分配一个唯一的 Identifer(id),然后您可以创建自己的数据堆栈方法来删除特定任务。

您可以为任务示例创建数据模型类或结构

class TaskData 
  var id: Int!
  var task: String!

  init(id: Int, task: String) 
    self.id = id
    self.task = task
  

将任务作为这个dataClass保存到coreData中。

当您删除该行时,捕获任务 ID 并将其从 coreDataStack 中删除。

一个好方法是创建一个TaskManager Singelton 类来处理所有核心数据方法。

【讨论】:

我不想删除 coreData 中的任务,因为我想每天使用 coreData 中的所有任务重新加载我的 tableview。这是一个任务重复应用程序。

以上是关于如何持久化 tableview 行?的主要内容,如果未能解决你的问题,请参考以下文章

如何查询打开的持久委托项目

具有选择器视图和持久性的 Tableview

如何将持久委托 ModelIndex 恢复为“正常”

如何在核心数据中持久化重复事务并将其呈现在表格视图中

如何在 cellEdit 之后强制从持久存储重新加载核心数据

自定义数组的自定义数组的持久化存储