• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

ios - NSFetchedResultsController - 用户驱动的更改

[复制链接]
菜鸟教程小白 发表于 2022-12-11 19:48:47 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题

概述

  • 我有一个 NSFetchedResultsController
  • 用户将能够添加新记录(编辑模式下的表格 View )
  • 当用户点击添加按钮时,我能够检测到事件并创建一个新的 Car(NSManagedObject 的子类,与 NSFetchedResultsController的谓词)

问题:

  • 当用户发起操作时,如何在表格 View 中插入新行?
  • 根据我当前的实现,应用崩溃了。崩溃消息如下。
  • 如何准确检测模型更改何时生效? (根据崩溃消息,我觉得我插入行太早了)

注意:

  • 我知道 NSFetchedResultsControllerDelegate 检测到模型更改,但问题是模型已更新,我需要表格 View 来匹配它。
  • 通常 NSFetchedResultsControllerDelegate 会检测模型更改,我可以使用委托(delegate)方法进行更新。
  • 我的问题是,既然用户添加了行,那么首先更新模型,然后表格 View 必须根据它进行调整。

引用:https://developer.apple.com/documentation/coredata/nsfetchedresultscontrollerdelegate

NSFetchedResultsController 的创建:

let fetchRequest : NSFetchRequest<Car> = Car.fetchRequest()

fetchRequest.predicate = NSPredicate(format: "color = %@", argumentArray: ["green"])

let orderIDSortDescriptor = NSSortDescriptor(keyPath: \Car.price, ascending: true)

fetchRequest.sortDescriptors = [orderIDSortDescriptor]

fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest,
                                                      managedObjectContext: context,
                                                      sectionNameKeyPath: nil,
                                                      cacheName: nil)

编辑风格

override func tableView(_ tableView: UITableView,
                        editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle {

    let newCarIndex = fetchedResultsController?.fetchedObjects?.count ?? 0

    let editingStyle : UITableViewCellEditingStyle

    switch indexPath.row {

    case newCarIndex:
        editingStyle = .insert

    default:
        break            
    }

    return editingStyle
}

提交用户操作

override func tableView(_ tableView: UITableView,
                        commit editingStyle: UITableViewCellEditingStyle,
                        forRowAt indexPath: IndexPath) {

    switch editingStyle {

    case .insert:
        createGreenCar(at: indexPath) //Creating a new Car with color = Green
        tableView.insertRows(at: [indexPath], with: .automatic) //This causes the app to crash
    default:
        break
    }
}

崩溃错误信息:

由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“无效更新:第 1 节中的行数无效。更新后现有节中包含的行数 (1) 必须等于更新前该节中包含的行数 (1),加上或减去从该节插入或删除的行数(1 插入,0 删除),加上或减去移入或移出该节的行数( 0 移入,0 移出)。'



Best Answer-推荐答案


感谢@Jake 和@pbasdf,他们的建议帮助我发现并纠正了问题。

我正在回答完整性。

根本原因:

我的表格 View 中有多个部分,我将行插入错误的部分。因此,当模型发生变化时,相关部分中的表格 View 行数并没有发生变化。

接近用户驱动的更新:

1。使用数组

我觉得将结果转换成一个数组并使用数组作为数据源而不是 NSFetchedResultsController 来进行用户驱动的更新会更好。

2。使用 NSFetchedResultsController:

当用户插入/删除/移动行时UITableViewDataSource方法被调用:

  • 当用户插入/删除行时tableView(_:commit:forRowAt会被调用
  • 当用户移动行时 tableView(_:moveRowAt:to 会被调用
  • 为上述方法相应地更新核心数据

更新核心数据会导致NSFetchedResultsControllerDelegate被调用

  • controller(_:didChange:at:for:newIndexPath 中执行以下操作:
    • 对于插入 - 添加 indexPaths
    • 对于删除 - 删除 indexPaths
    • 对于移动 - 什么都不做,因为 UI 已经是最新的(用户已经移动了行),稍后在 controllerDidChangeContent(_ 调用 tableView.reloadData() 延迟 0.5 秒

注意:

当用户在 iOS 11.2 上移动该行(使用 NSFetchedResultsController)时,我确实遇到了以下警告:

UITableView internal inconsistency: _visibleRows and _visibleCells must be of same length. _visibleRows

我不知道如何解决它,所以暂时坚持使用数组实现。

关于ios - NSFetchedResultsController - 用户驱动的更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49070451/

回复

使用道具 举报

懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关注0

粉丝2

帖子830918

发布主题
阅读排行 更多
广告位

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap