ios RXSwift - RxCollectionViewSectionedReloadDataSource -拖放移动(重新排序)

ebdffaop  于 2023-03-14  发布在  iOS
关注(0)|答案(2)|浏览(139)

我已经使用RxCollectionViewSectionedReloadDataSource将数据加载到UICollectionView中。

let dataSource = RxCollectionViewSectionedReloadDataSource<SectionModel<String, WorkGroup>>(
            configureCell: { (_, collectionView, indexPath, item) in
                guard let cell = collectionView
                        .dequeueReusableCell(withReuseIdentifier: WorkGroupCell.identifier, for: indexPath) as? WorkGroupCell else {
                            return WorkGroupCell()
                        }
                cell.viewModel = item
                return cell
            }
        )
        
        viewModel.items.bind(to: tileCollectonView.rx.items(dataSource: dataSource)).disposed(by: disposeBag)
 
        tileCollectonView.rx.setDelegate(self).disposed(by: disposeBag)

使用上面的代码,我可以显示数据。但我想拖放(重新排序)的单元格。
请让我知道我如何使用RxSwift重新排序。
我们将非常感谢您的帮助。

nhhxz33t

nhhxz33t1#

通常情况下,您需要一个状态机。
其中的逻辑相当简单:

struct State<Item> {
    var items: [Item] = []
}

func state<Item>(initialState: State<Item>, itemMoved: Observable<ItemMovedEvent>) -> Observable<State<Item>> {
    itemMoved
        .scan(into: initialState) { (state, itemMoved) in
            state.items.move(from: itemMoved.sourceIndex.row, to: itemMoved.destinationIndex.row)
        }
        .startWith(initialState)
}

extension Array
{
    mutating func move(from oldIndex: Index, to newIndex: Index) {
        if oldIndex == newIndex { return }
        if abs(newIndex - oldIndex) == 1 { return self.swapAt(oldIndex, newIndex) }
        self.insert(self.remove(at: oldIndex), at: newIndex)
    }
}

上面的例子使用了RxCocoa提供的ItemMovedEvent作为表视图,为了创建类似的集合视图,你需要将UICollectionViewDragDelegate Package 在一个委托代理中,关于如何做的文章可以在这里找到:Convert a Swift Delegate to RxSwift Observables

zbwhf8kr

zbwhf8kr2#

所以我假设您使用的是RxDataSources
设置datasource变量后,还需要设置两个属性:x1米1米1x,x1米2米1x

// in CollectionViewSectionedDataSource class
public typealias MoveItem = (CollectionViewSectionedDataSource<Section>, _ sourceIndexPath:IndexPath, _ destinationIndexPath:IndexPath) -> Void
public typealias CanMoveItemAtIndexPath = (CollectionViewSectionedDataSource<Section>, IndexPath) -> Bool
let dataSource = ...
dataSource.canMoveItemAtIndexPath = { dataSource, indexPath in
    return true
}
        
dataSource.moveItem = {dataSource, source, destination in
    ...
}

并使用UICollectionView方法来启动/更新/结束交互。在我的例子中,我添加了长按手势来处理拖动

//in viewDidLoad
    let startDragGesture = UILongPressGestureRecognizer(target: self, action: #selector(handleDragging))
    collectionView.addGestureRecognizer(startDragGesture)
    ...

    
    @objc func handleDragging(gesture: UILongPressGestureRecognizer){
        switch gesture.state {
        case .began:
            guard let indexPath = collectionView.indexPathForItem(at: gesture.location(in: collectionView)) else { return }
            
            collectionView.beginInteractiveMovementForItem(at: indexPath)
        case .changed:
            collectionView.updateInteractiveMovementTargetPosition(gesture.location(in: collectionView))
        case .ended:
            collectionView.endInteractiveMovement()
        default:
            collectionView.cancelInteractiveMovement()
        }
    }

你就可以把你的手机
moveItem闭包中,应该移动集合中实际数据。

相关问题