SwiftUI

SwiftUI 利用UICollectionView 并且实现拖拽

struct GridView<CellView: View>: UIViewRepresentable {

    let cellView: (Int) -> CellView
    let proxy: GeometryProxy
    var numbers: [Int]

    init(_ numbers: [Int], proxy: GeometryProxy, @ViewBuilder cellView: @escaping (Int) -> CellView) {
        self.proxy = proxy
        self.cellView = cellView
        self.numbers = numbers
    }

    func makeUIView(context: Context) -> UICollectionView {

        let layout = UICollectionViewFlowLayout()
        layout.scrollDirection = .vertical
        layout.minimumLineSpacing = 20
        layout.minimumInteritemSpacing = 10
        layout.itemSize = CGSize(width: 234, height: 240)

        let collectionView = UICollectionView(frame: proxy.frame(in: .global), collectionViewLayout: layout)
        collectionView.backgroundColor = bcBodyBackUIColor
        collectionView.register(GridCellView.self, forCellWithReuseIdentifier: "CELL")

        collectionView.dragInteractionEnabled = true
        collectionView.dataSource = context.coordinator
        collectionView.delegate = context.coordinator
        collectionView.contentInset = UIEdgeInsets(top: 28, left: 28, bottom: 28, right: 28)
        return collectionView
    }

    func updateUIView(_ uiView: UICollectionView, context: Context) {
    }

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    class Coordinator: NSObject, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
        var parent: GridView
        var collectionView: UICollectionView?

        init(_ parent: GridView) {
            self.parent = parent
        }
        func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
            self.collectionView = collectionView
            return parent.numbers.count
        }

        func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CELL", for: indexPath) as! GridCellView
            cell.layer.backgroundColor = bcBodyBackUIColor.cgColor
            cell.backgroundColor = .clear
            cell.cellView.rootView = AnyView(parent.cellView(parent.numbers[indexPath.row]).fixedSize())

            let tap = UILongPressGestureRecognizer(target: self, action: #selector(delectBtn(_:)))
            tap.minimumPressDuration = 0.1
            cell.addGestureRecognizer(tap)

            return cell
        }

        @objc func delectBtn(_ sender: UILongPressGestureRecognizer) {
            switch sender.state {
            case .began:
                let selectedCellIndex = self.collectionView!.indexPathForItem(at: sender.location(in: collectionView))
                self.collectionView!.beginInteractiveMovementForItem(at: selectedCellIndex!)
            case .changed:
                self.collectionView!.updateInteractiveMovementTargetPosition(sender.location(in: collectionView))
            case .ended:
                self.collectionView!.endInteractiveMovement()
            default:
                self.collectionView!.cancelInteractiveMovement()
            }
        }

        func collectionView(_ collectionView: UICollectionView, moveItemAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
            let tempMybook = self.parent.numbers[sourceIndexPath.item]
            self.parent.numbers.remove(at: sourceIndexPath.item)
            self.parent.numbers.insert(tempMybook, at: destinationIndexPath.item)
        }

    }
}
class GridCellView: UICollectionViewCell {
    public var cellView = UIHostingController(rootView: AnyView(EmptyView()))
    public override init(frame: CGRect) {
        super.init(frame: frame)
        configure()
    }
    public required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        configure()
    }
    private func configure() {
        contentView.addSubview(cellView.view)
        cellView.view.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            cellView.view.leftAnchor.constraint(equalTo: contentView.leftAnchor),
            cellView.view.rightAnchor.constraint(equalTo: contentView.rightAnchor),
            cellView.view.topAnchor.constraint(equalTo: contentView.topAnchor),
            cellView.view.bottomAnchor.constraint(equalTo: contentView.bottomAnchor)
            ])
        cellView.view.layer.masksToBounds = true
        cellView.view.layer.backgroundColor = bcBodyBackUIColor.cgColor
    }
}
struct MyView: View {

    var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]

    var body: some View {


        GeometryReader { proxy in
            GridView(self.numbers, proxy: proxy) { number in
                Text(String(number))
            }
        }.frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height - 150)

    }
}