繁体   English   中英

UICollectionView在重新排序过程中尝试使单元出队超出数据源范围

[英]UICollectionView attempts to dequeue cells beyond data source bounds while reordering is in progress

我已经实现了单元格重新排序的集合视图

class SecondViewController: UIViewController {

    @IBOutlet weak var collectionView: UICollectionView!
    private var numbers: [[Int]] = [[], [], []]

    private var longPressGesture: UILongPressGestureRecognizer!

    override func viewDidLoad() {
        super.viewDidLoad()

        for j in 0...2 {
            for i in 0...5 {
                numbers[j].append(i)
            }
        }

        longPressGesture = UILongPressGestureRecognizer(target: self, action: "handleLongGesture:")
        self.collectionView.addGestureRecognizer(longPressGesture)
    }

    func handleLongGesture(gesture: UILongPressGestureRecognizer) {

        switch(gesture.state) {

        case .Began:
            guard let selectedIndexPath = self.collectionView.indexPathForItemAtPoint(gesture.locationInView(self.collectionView)) else {
                break
            }
            collectionView.beginInteractiveMovementForItemAtIndexPath(selectedIndexPath)
        case .Changed:
            collectionView.updateInteractiveMovementTargetPosition(gesture.locationInView(gesture.view!))
        case .Ended:
            collectionView.endInteractiveMovement()
        default:
            collectionView.cancelInteractiveMovement()
        }
    }

}

extension SecondViewController: UICollectionViewDataSource {

    func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
        return numbers.count
    }

    func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
      let number = numbers[section].count
      print("numberOfItemsInSection \(section): \(number)")

      return number
    }

    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        print("cellForItemAtIndexPath: {\(indexPath.section)-\(indexPath.item)}")
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as! TextCollectionViewCell
        cell.textLabel.text = "\(numbers[indexPath.section][indexPath.item])"

        return cell
    }

    func collectionView(collectionView: UICollectionView, moveItemAtIndexPath sourceIndexPath: NSIndexPath, toIndexPath destinationIndexPath: NSIndexPath) {
        let temp = numbers[sourceIndexPath.section].removeAtIndex(sourceIndexPath.item)
        numbers[destinationIndexPath.section].insert(temp, atIndex: destinationIndexPath.item)
    }
}

在我尝试将项目从第0部分拖动到第2部分(不在屏幕上)之前,它工作正常。 当我将项目拖到集合视图的底部时,它会慢慢开始向下滚动。 在某个时刻(滚动到第1节时),应用程序崩溃并出现fatal error: Index out of range因为它试图在第1节中的索引6处请求单元格,而本节中只有6个项目。 如果我尝试将项目从第1部分拖到第2部分,则一切正常。

这是一个重现此问题的示例项目( 贷给NSHint ): https : //github.com/deville/uicollectionview-reordering

这是框架中的错误还是我缺少什么? 如果是前者,那么解决方法是什么?

我今天实际上遇到了这个问题。 最终问题出在itemAtIndexPath中-我引用数据源来获取单元格的某些属性:因此,超出范围的源崩溃了。 对我来说,解决方法是在itemAtIndexPath中保留对当前拖动单元格的引用。 检查节的数据源长度与传递的NSIndexPath的比较,以及是否超出范围; 请参考拖动单元格的属性。

Likesuchas(在Obj-C中……尚未移至Swift):

    NSArray* sectionData = [collectionViewData objectAtIndex:indexPath.section];

    MyObject* object;

    if (indexPath.row < [sectionData count]) {
        object = [dataObject objectAtIndex:indexPath.row];
    } else {
        object = draggingCell.object;
    }

    [cell configureCell:object];

不知道这是否与您的确切问题相似; 但是这是我的,因为现在一切都按预期进行。 :)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM