본문 바로가기

이상/iOS

[iOS] UITableView Drag & Drop으로 Row 이동

반응형

UITableView Editing Mode에서 UITableView의 setEditing()를 이용하여 row를 움직였다.

 

UITableView Editing Mode에서의 Row 이동

 

사실 row를 이동시키는 기능만 필요할 경우

 

이 방식보다는 cell을 Long press하여 이동시키는 방법이 훨씬 효율적이다.

 

PC에서 바탕화면의 아이콘을 Drag & Drop으로 이동시키는 것처럼

 

UITableView의 Cell을 이동시키는 방법에 대해 정리한다.

 

 

 

1. dragInteractionEnabled, dragDelegate, dropDelegate 지정

 

viewDidLoad()에서 UITableView의 dragInteractionEnabled, dragDelegate, dropDelegate를 지정한다.

 

1
2
3
4
5
6
7
8
override func viewDidLoad() {
   self.tableView.delegate = self
    self.tableView.dataSource = self
    // Drag & Drop 기능을 위한 부분        
    self.exerciseTableView.dragInteractionEnabled = true
    self.exerciseTableView.dragDelegate = self
    self.exerciseTableView.dropDelegate = self
}
cs

 

 

ViewController에 지정해준 Delegate의 Instance Method를 추가해준다.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// MARK:- UITableView UITableViewDragDelegate
extension ViewController: UITableViewDragDelegate {
func tableView(_ tableView: UITableView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
        return [UIDragItem(itemProvider: NSItemProvider())]
    }
}
 
// MARK:- UITableView UITableViewDropDelegate
extension ViewController: UITableViewDropDelegate {
    func tableView(_ tableView: UITableView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UITableViewDropProposal {
        if session.localDragSession != nil {
            return UITableViewDropProposal(operation: .move, intent: .insertAtDestinationIndexPath)
        }
        return UITableViewDropProposal(operation: .cancel, intent: .unspecified)
    }
    func tableView(_ tableView: UITableView, performDropWith coordinator: UITableViewDropCoordinator) { }
}
cs

 

실행한다.

 

Drag & Drop Delegate 추가

 

 

2. tableView(_:moveRowAt:to:)

 

실행해보면 Drag & Drop이 되지만 Row가 제자리로 돌아가 버린다.

 

이제 UITableViewDataSource의 moveRowAt()을 구현하여 원하는대로 작동하게 하기 전에 !

 

예의상 Doc을 한 번 보자.

 

 

tableView(_:moveRowAt:to:)

 

move a row at a specific location

 

'특정 위치로 row를 이동' 이라고 돼있고,

 

Declaration을 보면 sourceIndexPathdestinationIndexPath가 있다.

 

source -> dest로 이동시키나보다.

 

Doc의 tableView(_:moveRowAt:to:)

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// MARK:- UITableView UITableViewDataSource
extension RoutineDetailViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int-> Int {
        return self.list.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "tableViewCell"for: indexPath) as! TableViewCell
        let item = self.list[indexPath.row]
        cell.titleLabel.text = item.title
        return cell
    }
    // Row Editable true
    func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
        return true
    }
    // Swipe Right-to-left
    func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
        if (editingStyle == .delete) {
            self.list.remove(at: indexPath.row)
        }
    }
    // Move Row Instance Method
    func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
        print("\(sourceIndexPath.row) -> \(destinationIndexPath.row)")
        let moveCell = self.list[sourceIndexPath.row]
        self.list.remove(at: sourceIndexPath.row)
        self.list.insert(moveCell, at: destinationIndexPath.row)
    }
}
cs

 

이 전 글인 Swipe Delete의 소스를 재사용해서 맨 아래에 추가해줬다.

 

대학교 C언어 수업시간에 배웠던 temp로 변수 돌리듯이 돌려서 row를 source에서 dest로 옮겼다.

 

다시 실행!

 

Move Row with Drag & Drop



완성이다.

 

끝.

 

 

 

처음에는 tableview reorder라고 검색을 했는데 간단하게 구현된게 없어서

 

어떤 사람이 Objective-C로 직접 LongPressGestureRecognizer로 구현해놓은걸 보고

 

1시간동안 Swift로 바꾸고 돌려보니 LongPressGestureRecognizer가 작동하기는 했는데 뭔가 이상했다.

 

그러다 내가 예전에 쓴 글에 있던게 그제서야 기억나서 보고 moveRowAt()으로 검색하니까

 

애플이 iOS 11부터 Drag & Drop 기능을 추가해줬다는 글이 있어서 아주 손쉽게 구현했다.

 

역시 머리가 안 좋거나 너무 복잡하게 생각하면 몸이 피곤하다.

반응형