Ошибка Swift UICollectionView при перемещении ячейки - PullRequest
0 голосов
/ 19 февраля 2020

при перемещении ячеек в ViewController возникает следующая ошибка: движущаяся ячейка начинает дергаться на мгновение, когда она перемещается в исходное положение во время движения. Вот как это выглядит:

https://youtu.be/lJ-NXv6GMXc

import UIKit

class FrameCollection : UICollectionView, UICollectionViewDelegate, UICollectionViewDataSource {
    private let layout = FramesCollectionLayout()
    private var frames : [Int] = []
    private var recognizer : UILongPressGestureRecognizer!

    func collectionView(_ collectionView: UICollectionView, moveItemAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
        let a = frames.remove(at: sourceIndexPath.item)

        frames.insert(a, at: destinationIndexPath.item)
    }

    func collectionView(_ collectionView: UICollectionView, targetIndexPathForMoveFromItemAt originalIndexPath: IndexPath, toProposedIndexPath proposedIndexPath: IndexPath) -> IndexPath {
        return proposedIndexPath
    }

    func collectionView(_ collectionView: UICollectionView, canMoveItemAt indexPath: IndexPath) -> Bool {
        true
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        frames.count
       }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        //print("cell create")
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "test", for: indexPath) as! testCell
            cell.setNum(num: frames[indexPath.item])
        return cell
       }

    @objc func move(_ sender : UILongPressGestureRecognizer){
        switch sender.state {
        case .began:
            if let pos = indexPathForItem(at: sender.location(in: sender.view)) {
                beginInteractiveMovementForItem(at: pos)
            }
        case .changed:
            updateInteractiveMovementTargetPosition(CGPoint(x: sender.location(in: self).x,y: 36))
        case .ended:
             endInteractiveMovement()
        case .cancelled:
            cancelInteractiveMovement()
        default: break
        }
    }

    init(frame: CGRect) {
        super.init(frame: frame, collectionViewLayout: layout)

        for i in 0..<25 {
            frames.append(i)
        }

        register(testCell.self, forCellWithReuseIdentifier: "test")
        delegate = self
        dataSource = self
        isUserInteractionEnabled = true

        recognizer = UILongPressGestureRecognizer(target: self, action: #selector(move(_:)))
        addGestureRecognizer(recognizer)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

class FramesCollectionLayout : UICollectionViewLayout{
    private var attributes : [UICollectionViewLayoutAttributes] = []

    var contentWidth = 0

    override var collectionViewContentSize: CGSize {
        return CGSize(width: Int(contentWidth), height: Int(collectionView!.bounds.height))
    }

    override func prepare() {
        if(attributes.count == 0){
            for item in 0..<collectionView!.numberOfItems(inSection: 0){
                let index = IndexPath(item: item, section: 0)
                let frame = CGRect(x: 6 + item * 42, y: 6, width: 36, height: 60)
                let attribute = UICollectionViewLayoutAttributes(forCellWith: index)
                attribute.frame = frame
                attributes.append(attribute)
            }
            contentWidth = 6 + 42 * collectionView!.numberOfItems(inSection: 0)
        }
    }

    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        var visibleAttributes : [UICollectionViewLayoutAttributes] = []
        for attribute in attributes{
            if attribute.frame.intersects(rect){
                visibleAttributes.append(attribute)
            }
        }
        return visibleAttributes
    }

    override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
        return attributes[indexPath.item]
    }
}

class testCell : UICollectionViewCell{
    private var bg : UILabel = UILabel()

    override init(frame: CGRect) {
        super.init(frame: frame)

        bg.text = "test"
        bg.frame = contentView.bounds

        contentView.backgroundColor = .gray
        //contentView.layer.shouldRasterize = true
        contentView.addSubview(bg)
    }
    func setNum(num : Int){
        bg.text = "\(num)"
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

В чем причина этой ошибки и как ее можно исправить? (для тестирования вы можете просто скопировать код, создать коллекцию FrameCollection и вставить ее в проект)

...