断言CollectionView.reloadItems失败(位于:CollectionView.indexPathsForVisibleItems)

时间:2018-12-10 18:39:20

标签: ios swift uicollectionview nsfetchedresultscontroller

我有两个水平的collectionViews-一个显示多个帖子,另一个显示与发布日期相对应的时间轴。每天在时间轴collectionView中都有一个垂直单元格。如果该天有帖子,则会以彩色显示。

enter image description here

例如,在此图像中,有两个帖子在不同的日期。活动帖子比其他帖子更厚。

为了使事情变得更复杂,将使用NSFetchedResultsController加载帖子,以便在添加或删除帖子时,postsCollectionView和时间轴将更新。这是发生这种情况时调用的NSFetchedResults方法:

extension TimelineViewController: NSFetchedResultsControllerDelegate {
    //autoUpdate Stuff
    func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>,
                    didChange anObject: Any,
                    at indexPath: IndexPath?,
                    for type: NSFetchedResultsChangeType,
                    newIndexPath: IndexPath?){
        switch type {
        case .insert:
            print("Insert Object: \(String(describing: newIndexPath))")
            blockOperations.append(
                BlockOperation(block: { [weak self] in
                    if let this = self {
                        this.postsCollectionView!.insertItems(at: [newIndexPath!])
                    }
                })
            )
        case .update:
            blockOperations.append(
                BlockOperation(block: { [weak self] in
                    if let this = self {
                        this.postsCollectionView!.reloadItems(at: [indexPath!])
                    }
                })
            )
        case .move:
            blockOperations.append(
                BlockOperation(block: { [weak self] in
                    if let this = self {
                        this.postsCollectionView!.moveItem(at: indexPath!, to: newIndexPath!)
                    }
                })
            )
        case .delete:
            blockOperations.append(
                BlockOperation(block: { [weak self] in
                    if let this = self {
                        this.postsCollectionView!.deleteItems(at: [indexPath!])
                    }
                })
            )
        default: break
        }
    }

    func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
        postsCollectionView!.performBatchUpdates({ () -> Void in
            for operation: BlockOperation in self.blockOperations {
                operation.start()
            }
        }, completion: { (finished) -> Void in
            self.loadTimeline()
            self.blockOperations.removeAll(keepingCapacity: false)
        })
    }
}

这是在完成动画后调用的loadTimeline函数

func loadTimeline(){
        postTimes = posts.fetchedObjects?.map{ $0.timeStamp } as! [Date]
        if postTimes.count > 0 {
            detailsView.isHidden = false
            timelineCollectionView.isHidden = false
            firstPostDate = postTimes.first
            lastPostDate = postTimes.last
            for (i,postTime) in postTimes.enumerated() {
                let day = postTime.days(from: Calendar.current.startOfDay(for: firstPostDate!))
                indexMap[day] = IndexPath(row: i, section: 0)
            }
            let timelineStartDay = Calendar.current.date(byAdding: .day, value: 0, to: firstPostDate!)
            timelineStart = Calendar.current.startOfDay(for: timelineStartDay!)
            timelineEnd = Calendar.current.date(byAdding: .day, value: 0, to: lastPostDate!)

            timelineCollectionView.reloadItems(at: timelineCollectionView.indexPathsForVisibleItems)

            let postTimeStamp = currentPost.timeStamp as Date?
            let timelineIndex = postTimeStamp?.days(from: timelineStart!)
            print(timelineIndex,"timelineIndex")
            let cellIndexPath = IndexPath(item: timelineIndex!,section: 0)
            self.selectedIndexPath = cellIndexPath
            timelineCollectionView.scrollToItem(at: cellIndexPath, at: .centeredHorizontally, animated: true)
        } else {
            timelineCollectionView.isHidden = true
            detailsView.isHidden = true
        }
    }

这样做时,我会得到断言错误:

2018-12-10 10:30:10.696195-0800 SweatNetOffline[3922:22319314] *** Assertion failure in -[UICollectionView _endItemAnimationsWithInvalidationContext:tentativelyForReordering:animator:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKitCore_Sim/UIKit-3698.84.15/UICollectionView.m:5956
2018-12-10 10:30:10.705622-0800 SweatNetOffline[3922:22319314] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'attempt to insert item 1 into section 0, but there are only 1 items in section 0 after the update'

请注意,此错误是由timelineCollectionView.reloadItems(at: timelineCollectionView.indexPathsForVisibleItems)引起的。

如果我将其注释掉,则不会崩溃,但是当然不会重新加载时间轴。

时间轴的数据也设置如下:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    if collectionView == timelineCollectionView {
        let cell = timelineCollectionView.dequeueReusableCell(withReuseIdentifier: "dayCell", for: indexPath) as! TimelineCollectionViewCell
        let cellDate = Calendar.current.date(byAdding: .day, value: indexPath.item, to: self.timelineStart!)!
        if postTimes.contains(where: { Calendar.current.isDate(cellDate, inSameDayAs: $0) }) {
            cell.backgroundColor = UIColor(red:0.22, green:0.45, blue:0.62, alpha:1.0)
        }
        return cell
    } else {
        ...  // for the post cell
    }
}

因为postTimes是在loadTimeline()中更新的,所以我不认为需要调用reloadData,我只想重新加载更新的postTimes中可见的项目。为什么reloadItems调用在这里不起作用?

0 个答案:

没有答案