【问题标题】:CollectionView.reloadData() outputs cells in incorrect orderCollectionView.reloadData() 以错误的顺序输出单元格
【发布时间】:2018-09-19 15:31:37
【问题描述】:

我正在开发一个应用程序,该应用程序需要在登录后同步到服务器以获取用户创建并保存到服务器的所有活动。目前,当用户登录 getActivity() 函数时,该函数发出 API 请求并返回响应,然后处理该响应。

假设用户在服务器上按此顺序保存了 4 个活动(顺序由创建/保存活动的时间决定);

  • 测试
  • 鲍勃
  • cvb
  • 测试

查看 JSONHandler.getActivityResponse ,结果似乎顺序正确。如果请求成功,在要显示这些活动的主页上,我当前会像这样循环它们;

WebAPIHandler.shared.getActivityRequest(completion:
        {
            success, results in DispatchQueue.main.async {
                    if(success)
                    {
                        for _ in (results)!
                        {
                            guard let managedObjectContext = self.managedObjectContext else { return }

                            let activity = Activity(context: managedObjectContext)

                            activity.name = results![WebAPIHandler.shared.idCount].name
                            print("activity name is - \(activity.name)")
                            WebAPIHandler.shared.idCount += 1
                        }
                    }

并且for循环内的打印也是按照预期的顺序输出的;

activity name is - Optional("Test")
activity name is - Optional("Bob")
activity name is - Optional("cvb")
activity name is - Optional("Testing")

CollectionView 然后会插入新的单元格,但它似乎以错误的顺序。我在主页上使用轮播布局,例如“cvb”对象出现在列表的第一位,“bob”在列表中的第三位。我正在使用以下

 func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?)
{
    switch (type)
    {
    case .insert:

        if var indexPath = newIndexPath
        {
//                    var itemCount = 0
//                    var arrayWithIndexPaths: [IndexPath] = []
//                
//                    for _ in 0..<(WebAPIHandler.shared.idCount)
//                    {
//                        itemCount += 1
//                        
//                        arrayWithIndexPaths.append(IndexPath(item: itemCount - 1, section: 0))
//                        print("itemCount = \(itemCount)")
//                }

            print("Insert object")
//                walkThroughCollectionView.insertItems(at: arrayWithIndexPaths)
            walkThroughCollectionView.reloadData()

    }

您可以看到为什么我尝试使用 collectionView.insertItems() 但这会导致错误说明:

Invalid update: invalid number of items in section 0.  The number of items contained in an existing section after the update (4) must be equal to the number of items contained in that section before the update (4), plus or minus the number of items inserted or deleted from that section (4 inserted, 0 deleted)

我看到很多其他答案都提到了reloadData() 将如何解决这个问题,但我真的被困在这一点上。我已经使用 swift 几个月了,这是我第一次真正不知所措。我还意识到,轮播中显示的顺序也与传递相同数据的单独 viewController 不同。我只是不知道为什么结果以正确的顺序返回,但随后以错误的顺序显示。有没有办法在调用reloadData() 后对 collectionView 中的数据进行排序,还是我从错误的角度看这个?

任何帮助将不胜感激,干杯!

【问题讨论】:

  • reloadData 从不安排响应。如果不是您为每个响应添加id,则必须确保响应按预期排序,然后使用array.filter()

标签: json swift core-data uicollectionview reloaddata


【解决方案1】:

集合视图的顺序由获取结果控制器的排序描述符指定。

通常插入新NSManagedObject的工作流程是

  • 将新对象插入托管对象上下文中。
  • 保存上下文。这会调用委托方法 controllerWillChangeContentcontroller(:didChange:at: 等。
  • controller(:didChange:at: 中,使用insertItems(at: 将单元格插入到集合视图中,仅此而已。请勿在此方法中调用reloadData()

【讨论】:

  • 非常感谢,我没有意识到我必须专门调用 managedObjectContext.save() 因为我只是假设当单元格出现时它被保存在某个地方哈哈。非常感谢!
猜你喜欢
  • 2017-06-06
  • 2014-12-12
  • 1970-01-01
  • 2015-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-02
相关资源
最近更新 更多