[swift] Swift DeepDiff를 활용하여 테이블뷰에서 드래그를 통한 이동 처리하기

테이블뷰에서 셀의 이동 기능을 구현하려면 보통 tableView(_:moveRowAt:to:) 메서드를 구현하여 이동 후 데이터를 업데이트합니다. 하지만 이 방법은 기존 배열을 직접 수정해야 하기 때문에 번거롭고 실수가 발생할 수 있습니다.

이러한 문제를 해결하기 위해 Swift DeepDiff 라이브러리를 사용하여 테이블뷰에서 드래그를 통한 이동을 처리하는 방법을 알아보겠습니다. DeepDiff는 변경 사항을 탐지하고 애니메이션하는 데 사용되는 강력한 라이브러리입니다.

DeepDiff 설치하기

먼저 DeepDiff를 설치하기 위해 Podfile에 다음과 같이 추가합니다.

pod 'DeepDiff'

그런 다음 터미널에서 프로젝트 디렉토리로 이동하여 다음 명령을 실행합니다.

pod install

드래그 이동 처리하기

우선 테이블뷰에서 드래그 이동을 사용할 ViewController에 UITableViewDelegateUITableViewDragDelegate, UITableViewDropDelegate 프로토콜을 채택합니다.

class MyViewController: UIViewController, UITableViewDelegate, UITableViewDragDelegate, UITableViewDropDelegate {
    // ...
}

그런 다음 드래그 이동을 활성화하고 이벤트를 처리할 수 있는 메서드를 구현합니다.

class MyViewController: UIViewController, UITableViewDelegate, UITableViewDragDelegate, UITableViewDropDelegate {
    // ...

    func tableView(_ tableView: UITableView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
        // 드래그할 아이템을 반환하는 로직 작성
    }

    func tableView(_ tableView: UITableView, performDropWith coordinator: UITableViewDropCoordinator) {
        // 드롭한 아이템을 처리하는 로직 작성
        // DeepDiff를 사용하여 데이터 업데이트
    }

    func tableView(_ tableView: UITableView, canHandle session: UIDropSession) -> Bool {
        // 드롭을 처리할 수 있는지 여부를 반환하는 로직 작성
    }

    func tableView(_ tableView: UITableView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UITableViewDropProposal {
        // 드롭 동작을 업데이트하는 로직 작성
    }
}

마지막으로, 드래그 이동 후 데이터를 업데이트하기 위해 DeepDiff 라이브러리를 사용합니다. 드롭 이벤트가 발생한 후, performDropWith 메서드 내에서 DeepDiff를 사용하여 변경된 데이터를 감지하고 애니메이션을 적용합니다.

func tableView(_ tableView: UITableView, performDropWith coordinator: UITableViewDropCoordinator) {
    // 드롭한 아이템을 처리하는 로직 작성
    // DeepDiff를 사용하여 데이터 업데이트
    guard let destinationIndexPath = coordinator.destinationIndexPath, let item = coordinator.items.first else { return }

    let sourceIndexPath: IndexPath
    if let indexPath = item.sourceIndexPath {
        sourceIndexPath = indexPath
    } else {
        let row = destinationIndexPath.row >= tableView.numberOfRows(inSection: destinationIndexPath.section) ? tableView.numberOfRows(inSection: destinationIndexPath.section) - 1 : destinationIndexPath.row
        sourceIndexPath = IndexPath(row: row, section: destinationIndexPath.section)
    }

    // DeepDiff를 사용하여 변경된 데이터를 감지
    let changes = diff(old: dataArray, new: dataArray.move(from: sourceIndexPath.row, to: destinationIndexPath.row))

    // 변경 사항에 애니메이션 적용
    tableView.reload(changes: changes, with: .automatic) { data in
        dataArray = data
    }
}

위 예시에서 dataArray는 테이블뷰에 표시될 데이터 배열이며, diff(old:new:) 메서드와 move(from:to:) 메서드는 DeepDiff의 기능을 활용하여 배열의 변경 사항을 탐지하고 데이터를 이동시키는 역할을 합니다.

이제 테이블뷰에서 드래그를 통한 이동이 가능한 화면을 만들었습니다. DeepDiff를 사용하여 변경 사항을 탐지하고 데이터를 업데이트하면서 안정성을 확보할 수 있습니다.

참고