【问题标题】:Delete item from CollectionView with sections iOS Swift使用 iOS Swift 部分从 CollectionView 中删除项目
【发布时间】:2019-04-09 04:30:53
【问题描述】:

我有一个带有部分(2 个部分)的 CollectionView。当我从第 1 节中删除一个单元格时,它的删除非常好。但是当我从第 0 部分删除一个单元格时,我的应用程序崩溃并出现如下错误:

第 0 节中的项目数无效。更新后现有节中包含的项目数 (5) 必须等于更新前该节中包含的项目数 (5),加上或减去数字从该部分插入或删除的项目数(0 插入,1 个删除)加上或减去移入或移出该部分的项目数(0 移入,0 移出)。与 userInfo (null)

在从 collectionView 中删除项目之前,我在 performBatchUpdates 中从我的数据源中删除它:

extension MainCollectionViewController: NSFetchedResultsControllerDelegate {
    func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
        collectionView?.performBatchUpdates({ [weak self] in
            guard let self = self else { return }

            items = controller.fetchedObjects as! [Item]
            items2 = items.chunked(into: 5)

            self.collectionView?.deleteItems(at: [self.deletedItemIndex!])
        })
    }
}

extension Array {
    func chunked(into size: Int) -> [[Element]] {
        return stride(from: 0, to: count, by: size).map {
            Array(self[$0 ..< Swift.min($0 + size, count)])
        }
    }
}

func chunked - 是一个像这样对数组进行切片的函数(5 个部分):

分块前:

[1,2,3,4,5,6,7,8,9,10]

分块后:

[
    [1, 2, 3, 4, 5], // first section in collectionView
    [6, 7, 8, 9, 10], // second section in collectionView
] 

我使用以下函数将我的项目从 Core Data 填充到 collectionView:

    override func numberOfSections(in collectionView: UICollectionView) -> Int {
        print("call numberOfSections")
        //3
        return items2.count
    }

    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        print("call numberOfItemsInSection, current section is \(section)")
        //4
        return items2[section].count
    }

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CollectionViewCell

        let item = items2[indexPath.section][indexPath.row]

        cell.itemNameTextLabel.text = item.name
        cell.itemImageView.image = UIImage(data: item.image! as Data)

        return cell
    }
}

当用户长按项目(单元格)时,从 collectionView 和 CoreData 中删除项目。删除过程在这里:

@objc func handleLongPress(gesture: UILongPressGestureRecognizer!) {
    if gesture.state != .ended {
        return
    }

    let p = gesture.location(in: self.collectionView)

    if let indexPath = self.collectionView?.indexPathForItem(at: p) {
        let fetchRequest: NSFetchRequest<Item> = Item.fetchRequest()

        fetchRequest.predicate = NSPredicate(format: "name == %@", self.items2[indexPath.section][indexPath.row].name!)

        do {
            if let context = (UIApplication.shared.delegate as? AppDelegate)?.persistentContainer.viewContext {
                let selectedItem = try context.fetch(fetchRequest)[0]
                //save deleted item index in var that use it index in performBatchUpdatesBlock
                deletedItemIndex = IndexPath(row: indexPath.row, section: indexPath.section)

                context.delete(selectedItem)

                do {
                    try context.save()
                    print("Save!")
                } catch let error as NSError {
                    print("Oh, error! \(error), \(error.userInfo)")
                }
            }
        } catch {
            print(error.localizedDescription)
        }
    }
}

此过程的图像: enter image description here

我的项目如 Apple Books 应用。我想重复删除图书的过程...

我的完整代码是here (GitHub)。 Plis,使用 iPhone SE 模拟器。我在 items.plist 文件中的数据并在第一次运行应用程序时自动保存到 CoreData。

我的代码哪里出错了?

【问题讨论】:

    标签: ios swift core-data uicollectionview


    【解决方案1】:

    也许,问题是您删除了第 0 节的一项,删除后第 0 节仍然具有删除前相同数量的项目,因为您在每次删除后“重新分配”了项目。

    【讨论】:

    • 当我从第 0 节中删除项目时,本节中的元素必须是 5 个元素,然后才删除
    • 尝试仅从数据源中删除数据并重新加载项目,而不是调用self.collectionView?.deleteItems
    • 好的,我没有调用 self.collectionView?.deleteItems 并调用 self.collectionView.reloadItems(at: [deletedItemIndex!]) 但我有错误是第 1 节中的项目数无效
    【解决方案2】:

    当您从 CollectionView 中删除时,您还应该从底层数据数组 (items2) 中删除。

    func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
        collectionView?.performBatchUpdates({ [weak self] in
            guard let self = self else { return }
    
            items = controller.fetchedObjects as! [Item]
            items2 = items.chunked(into: 5)
    
            for indexPath in self.deletedItemIndex! {
               items2[indexPath.section].remove(at: indexPath.row)
            }
            self.collectionView?.deleteItems(at: [self.deletedItemIndex!])
        })
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-27
      • 1970-01-01
      • 1970-01-01
      • 2017-12-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多