保存已编辑的核心数据实体未保存
Posted
技术标签:
【中文标题】保存已编辑的核心数据实体未保存【英文标题】:Saving an edited Core Data entity is not being saved 【发布时间】:2019-01-28 01:14:05 【问题描述】:我有一个包含多个部分的 TableView,这些部分使用 Core Data 框架填充了实体(称为“项目”)。在 cellForRowAt 委托方法中,我调用了一个回调,该回调在用户按下“Enter”键时调用。此回调应将他们刚刚在单元格文本字段中键入的文本保存到核心数据模型,然后在其正下方添加一个新的空单元格。
所有这些都有效,除非该部分为空并且您尝试将 item.name 设置为等于 textfield.text。如果我向该部分添加多个项目,那么它将保存我刚刚创建并添加到数据模型中的所有单元格,但第一个单元格除外。
起初我正在更新项目,然后保存上下文,但我会收到一条错误消息,类似于“错误:从上下文中删除托管对象后对其进行变异”。请参阅下面的代码。
/// Customize the contents of the cell
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let cell = tableView.dequeueReusableCell(withIdentifier: homeCellId, for: indexPath) as! HomeTableViewCell
cell.delegate = self
let item = items[indexPath.section][indexPath.row]
cell.nameText.text = item.name
/// Called when user hits Enter on the keyboard
/// This allows them to enter a new item
cell.addNewCell = [weak self] newTitle in
guard let `self` = self else return // Capture self
if cell.nameText.text != ""
let newTitle: String = cell.nameText.text! // Grab the name øf the item the user just entered
let itemToUpdate = self.items[indexPath.section][indexPath.row] // Grab the item they typed
itemToUpdate.name = cell.nameText.text
self.saveContext()
// Create reference to indexpath below the existing cell
let newIndexPath = IndexPath(row: indexPath.row+1, section: indexPath.section) // Set the indexPath to the cell below
// Create new dummy item
let newPlaceholderItem = self.coreDataManager.addItem(toCategory: self.categories[indexPath.section], withItemName: "")
// Add dummy item to tableview array
self.items[indexPath.section].append(newPlaceholderItem)
self.tableView.insertRows(at: [newIndexPath], with: .automatic) // Insert it into the tableView
else
print("Can not add new cell since current cell is empty")
return cell
经过大量谷歌搜索后,我发现解决上述错误的方法是使用下图所示的 performBackgroundTask()。
/// Customize the contents of the cell
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let cell = tableView.dequeueReusableCell(withIdentifier: homeCellId, for: indexPath) as! HomeTableViewCell
cell.delegate = self
let item = items[indexPath.section][indexPath.row]
cell.nameText.text = item.name
/// Called when user hits Enter on the keyboard
/// This allows them to enter a new item
cell.addNewCell = [weak self] newTitle in
guard let `self` = self else return // Capture self
if cell.nameText.text != ""
let newTitle: String = cell.nameText.text! // Grab the name øf the item the user just entered
let itemToUpdate = self.items[indexPath.section][indexPath.row] // Grab the item they typed
let container = (UIApplication.shared.delegate as! AppDelegate).persistentContainer // Grab the persistent container
container.performBackgroundTask (context) in
// Make sure the object isn't null
guard let queueSafeItem = context.object(with: itemToUpdate.objectID) as? Item else
print("Error, could not update item.")
return
queueSafeItem.name = newTitle // Update the title of the item
// Save the change that the user made to the cell he just edited
do
print("Saving context after modifying item")
try context.save()
catch
print("Error saving when creating new cell: \(error)")
// Create reference to indexpath below the existing cell
let newIndexPath = IndexPath(row: indexPath.row+1, section: indexPath.section) // Set the indexPath to the cell below
// Create new dummy item
let newPlaceholderItem = self.coreDataManager.addItem(toCategory: self.categories[indexPath.section], withItemName: "")
// Add dummy item to tableview array
self.items[indexPath.section].append(newPlaceholderItem)
self.tableView.insertRows(at: [newIndexPath], with: .automatic) // Insert it into the tableView
else
print("Can not add new cell since current cell is empty")
return cell
【问题讨论】:
【参考方案1】:经过一些调试,我似乎没有正确保存“虚拟”单元格,不得不重新格式化一些代码。 Xcode 或 Swift 端没有错误 - 只是常见的程序员错误。
【讨论】:
以上是关于保存已编辑的核心数据实体未保存的主要内容,如果未能解决你的问题,请参考以下文章