아이폰 기본 어플인 메모나 알람에서 오른쪽에서 왼쪽으로 swipe하면 공유/삭제 할 수 있는 버튼이 나타나는데,
이번 프로젝트에서 적용해야해서 아래와 같이 뷰를 구현해보고 Action도 연결해볼거다.
테이블 뷰의 각 cell에 Swipe해서 Action을 설정하려면, UITableViewDelegate에 있는
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration?
메서드를 사용하면 된다.
메서드 이름 상당히 길지만.. 중간에 trailingSwipeActions~~ 이 부분을 보면, 어떤 cell을 trailing swipe(오른쪽 -> 왼쪽) 했을 때의 action을 정해주는 메서드라고 생각하면 될 것 같다. 지금 사용할 메서드는 trailing이니까 당연히 leading 메서드도 따로 있다. leading을 설정해주면 왼쪽 -> 오른쪽으로 swipe 했을 때 Action들이 왼쪽에 생길 것 같다.
이 메서드는 UISwipeActionsConfiguration?
을 반환하는데, 이 클래스의 정의는 "테이블의 row(행)을 스와이프할 때 수행할 action의 집합 (set)"이라고 되어 있다.
그래서 trailing 메서드 안에서 이 UISwipeActionsConfiguration?
라는 set 안에 들어갈 원하는 action들을 추가해주고 리턴해주면 끝!인듯하다.
이 UISwipeActionsConfiguration?
에 추가될 action들은 UIContextualAction 타입으로 생성한다.
UIContextualAction이라는 다소 와닿지 않는 네이밍이지만, 정의를 보면 "사용자가 테이블의 row(행)을 스와이프 할 때 표시할 작업(action)"이라고 나와있다.
나는 공유랑 삭제 action을 추가할거니까, 아래와 같이 2개의 UIContextualAction을 선언해주었다.
func tableView(_ tableView: UITableView,
trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath)
-> UISwipeActionsConfiguration? {
let share = UIContextualAction(style: .normal, title: "") { (_, _, success: @escaping (Bool) -> Void) in
// 원하는 액션 추가
let shareActivity = UIActivityViewController(activityItems: [diary], applicationActivities: nil)
self.present(shareActivity, animated: true)
success(true)
}
let delete = UIContextualAction(style: .normal, title: "") { (_, _, success: @escaping (Bool) -> Void) in
// 원하는 액션 추가
tableView.deleteRows(at: [indexPath], with: .fade)
success(true)
}
// 각 ContextualAction 대한 설정
share.backgroundColor = .systemBlue
share.image = UIImage(systemName: "square.and.arrow.up")
delete.backgroundColor = .systemRed
delete.image = UIImage(systemName: "trash.fill")
// UISwipeActionsConfiguration에 action을 추가하여 리턴
return UISwipeActionsConfiguration(actions: [delete, share])
}
}
UIContextualAction의 handler 부분을 보면 파라미터가 3개나 있는데, 각각 UIContextualAction, UIView, @escaping (Bool) -> Void -> Void 타입이다.
Contextual closure type '(UIContextualAction, UIView, @escaping (Bool) -> Void) -> Void' expects 3 arguments
여기서는 첫번째와 두번째 파라미터는 쓰이지 않아서 "_"로 대체했고, @escaping closure만 true로 설정해주었다.
그리고 마지막에 리턴할 때 set 내부의 ContextualAction의 순서가 [delete, share] 이렇게 되어있는데
trailing 기준이라서 그런지 이렇게 해야 share -> delete의 순서로 나오게 된다.
참고자료