UITableView Editing Mode에서 UITableView의 setEditing()를 이용하여 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 |
실행한다.
2. tableView(_:moveRowAt:to:)
실행해보면 Drag & Drop이 되지만 Row가 제자리로 돌아가 버린다.
이제 UITableViewDataSource의 moveRowAt()을 구현하여 원하는대로 작동하게 하기 전에 !
예의상 Doc을 한 번 보자.
move a row at a specific location
'특정 위치로 row를 이동' 이라고 돼있고,
Declaration을 보면 sourceIndexPath와 destinationIndexPath가 있다.
source -> dest로 이동시키나보다.
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로 옮겼다.
다시 실행!
완성이다.
끝.
처음에는 tableview reorder라고 검색을 했는데 간단하게 구현된게 없어서
어떤 사람이 Objective-C로 직접 LongPressGestureRecognizer로 구현해놓은걸 보고
1시간동안 Swift로 바꾸고 돌려보니 LongPressGestureRecognizer가 작동하기는 했는데 뭔가 이상했다.
그러다 내가 예전에 쓴 글에 있던게 그제서야 기억나서 보고 moveRowAt()으로 검색하니까
애플이 iOS 11부터 Drag & Drop 기능을 추가해줬다는 글이 있어서 아주 손쉽게 구현했다.
역시 머리가 안 좋거나 너무 복잡하게 생각하면 몸이 피곤하다.
'이상 > iOS' 카테고리의 다른 글
[iOS] Alamofire로 API 호출하기 (+ CocoaPods 사용법) (0) | 2021.02.05 |
---|---|
[iOS] IB Designables - Failed to render and update auto layout status for ViewController: The agent threw an exception (0) | 2021.02.04 |
[iOS] UITableViewCell Swipe Delete (0) | 2021.02.02 |
[iOS] UIRefreshControl의 발견 (0) | 2020.07.15 |
[iOS] UITableView Swipe Actions (0) | 2020.07.14 |