【问题标题】:How to update the model after tableView was edited编辑 tableView 后如何更新模型
【发布时间】:2018-08-17 13:59:35
【问题描述】:

我通过编写一个单一的表格应用程序视图来学习 Swift,该视图在启动时列出了核心数据表(实体)的内容。然后用户可以重新排序表视图中的行。

我需要能够保存新排序的行,以便它们替换以前的数据库表,这样当用户再次启动应用程序时,会显示新的顺序。

编辑(重新排序)功能通过长按和调用激活

func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
    self.projectTableView.moveRow(at: sourceIndexPath, to: destinationIndexPath)
}

第二次长按会停用编辑功能:

    // Called when long press occurred
    @objc func handleLongPress(_ gestureRecognizer: UILongPressGestureRecognizer){
    if gestureRecognizer.state == .ended {
        let touchPoint = gestureRecognizer.location(in: self.projectTableView)
        if let indexPath = projectTableView.indexPathForRow(at: touchPoint) {
            if self.projectTableView.isEditing == true {
                self.projectTableView.isEditing = false
                db.updateAll()  //this is a stub
            } else {
                self.projectTableView.isEditing = true
            }
        }
    }
}

上面'handleLongPress'中对db.updateAll()的调用只是一个空白,我不知道如何更新数据库。有没有办法将新序列中tableView的内容读入数组,然后替换db中的表?感觉有点“蛮力”,但看不到任何其他解决方案。

【问题讨论】:

  • 也许在调用moveRowAt 时更新您的数据源(通过删除并重新插入项目)会更好?
  • @Sylvan 可以添加代码示例吗?
  • Core Data 中的记录是无序存储的。如果你想要一个特定的顺序,你必须添加一个index 属性并获取按index 排序的数据。在moveRowAt 中,您必须调整索引。只是移动行永远不会影响核心数据堆栈。
  • @vadian CoreData 是否有一个可以实现和获取的“id autoincrement”或类似的整数?很惊讶这样一个微不足道的(在 SQLite 中)函数在 CoreData 中不容易访问。

标签: swift uitableview core-data


【解决方案1】:

好的,您可以通过多种方式实现:

1- 使用 NSFetchedResultsController ,您可以在此处自动同步对核心数据持久性存储所做的更改与表视图, 这么快,步骤如下:

  • 符合NSFetchedResultsControllerDelegate
  • 用你的核心数据模型声明一个NSFetchedResultsController的实例
  • 创建一个NSFetchRequest,使用请求调用NSFetchedResultsController 初始化程序,然后将其分配给您之前声明的实例
  • 在您的实例上调用performFetch 方法
  • 将 viewController 设置为委托
  • 现在你可以实现委托了,在这里你想要didChange,就像这样:

    func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>,
                didChange anObject: Any,
                at indexPath: IndexPath?,
                for type: NSFetchedResultsChangeType,
                newIndexPath: IndexPath?) {
         switch type {
         /*
           ....
          */
         case .move:
              if let deleteIndexPath = indexPath {
                 self.tableView.deleteRows(at: [deleteIndexPath], with: .fade)
               }
    
              if let insertIndexPath = newIndexPath {
                  self.tableView.insertRows(at: [insertIndexPath], with: .fade)
              }
         }
    

    }

2- 第二个选项,我个人更喜欢它而不是 NSFetchedResultscontroller

您可以在模型(核心数据模型)中添加属性。这可以是一个 Int,例如“orderNum”。 因此,当您获取请求时,您可以使用此属性对结果进行排序。

因此,如果您的表格视图单元格重新排列,则在实现 moveItem 方法后,您可以为所有对象更新此属性(循环遍历它们),它们将与显示的一样。

现在尝试保存您的托管对象上下文,

下次当你想获取请求时,你可以使用排序描述符对“orderNum”进行排序。

【讨论】:

【解决方案2】:

也许在调用 moveRowAt 时更新您的数据源(通过删除和重新插入项目)会更好?

比如:

// assuming your data source is an array of names
var data = ["Jon", "Arya", "Tyrion", "Sansa", "Winterfell"]

func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
    self.projectTableView.moveRow(at: sourceIndexPath, to: destinationIndexPath)

    let item = self.data.remove(at: sourceIndexPath.row)
    if sourceIndexPath.row > destinationIndexPath.row {
        // "Sansa" was moved to be between "Jon" and "Arya"
        self.data.insert(item, at: destinationIndexPath.row
    } else {
        // if the new destination comes after previous location i.e. "Sansa"
        // was moved to the end of the list
        self.data.insert(item, at: destinationIndexPath.row - 1
    }
}

【讨论】:

  • 实际上@mojtaba 建议为您的项目设置orderNum 值会是更好的解决方案
猜你喜欢
  • 2015-12-13
  • 1970-01-01
  • 2019-07-12
  • 1970-01-01
  • 1970-01-01
  • 2023-03-04
  • 1970-01-01
  • 1970-01-01
  • 2019-01-06
相关资源
最近更新 更多