TableView는 자체적으로 Delegate를 통해, 스와이프 액선을 지정해주고 있습니다.
저는 Cell을 스와이프해서 해당 Cell을 삭제해주는 작업을 구현해보았습니다.
Cell을 삭제할 때, Delete를 할 것인지 한번 확인하지 않으면, 사용자의 입장에서는 원치 않은 삭제를 할 수 있고
개발자는 이를 복구해줄 수 있는 툴을 만들어 주지 않는 이상, 반드시 사용자에게 정말 삭제할 것인지를 한번 확인받아야 한다고 생각합니다.
유저는 마치 쓰고 있던 블로그 글을 통채로 날린 느낌일 것이기 때문이에요..ㄸㄸ
다음은 제 tableView가 UITableViewDelegate를 채택해서 구현해야 하는 함수로
스와이프 하면 다음과 같은 삭제 버튼이 나타나게 됩니다.
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath)
-> UISwipeActionsConfiguration? {
let deleteAction = UIContextualAction(style: .destructive, title: nil) { (_, _, completionHandler) in
self.alertForSafeDeletion(indexPath: indexPath)
completionHandler(true)
}
deleteAction.image = UIImage(systemName: "trash")
deleteAction.backgroundColor = .systemRed
let configuration = UISwipeActionsConfiguration(actions: [deleteAction])
return configuration
}
이 configuration만 만들어서, 리턴 해주면, 스와이프 했을때, 저렇게 빨갛고 예쁜 삭제버튼이 짜잔하고 드러납니다ㅎㅎ
조금 더 설명을 해보자면, 먼저 deleteAction은 UIContextualAction으로 만들어줘야 하는데
UIContextualAction은 다음과 같이, 유저가 cell의 row를 스와이프 했을 때 일어나는 액션을 정의한다.
액선이 완료되면 destructive 스타일로 작동을 하게 되는데
이 스타일은 Cell 하나가 이렇게 사라지는 방식을 의미한다.
하지만 이게 정말로 지워지는 건 아니고, 지워지는 척만 하는것이다.
그리고 이 액션이 끝나고 나면 함수를 작동시켜서 실제로 DB나 리스트에서 지워주어야 한다!!
나의 경우는 다음 함수를 사용해서 해당 indexPath.row의 객체를 remove해주었다.
self.alertForSafeDeletion(indexPath: indexPath)
이 함수는 해당 indexPath를 삭제하는 함수인데,
나는 여기에 Alert로 한번 확인을 하는 과정을 거쳤다.
func alertForSafeDeletion(indexPath: IndexPath) {
impactFeedbackGenerator?.impactOccurred()
let alert = UIAlertController(title: nil, message: "정말 기록을 삭제할까요?", preferredStyle: .alert)
let yesAction = UIAlertAction(title: "네", style: .default) { _ in
// Yes를 눌렀을 때 할 일,
}
alert.addAction(yesAction)
let noAction = UIAlertAction(title: "아니오", style: .cancel) { _ in
// No를 눌렀을 때 할 일
}
alert.addAction(noAction)
present(alert, animated: true, completion: nil)
}
이렇게 Yes를 눌렀을 때는 지워주면 되고,
No를 눌렀을 때는 원하는 동작을 지정해주면 된다. (나같은 경우는 굳이 아무런 동작을 하지 않는다.)
내 전체 코드는 다음과 같다.
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath)
-> UISwipeActionsConfiguration? {
let deleteAction = UIContextualAction(style: .destructive, title: nil) { (_, _, completionHandler) in
self.alertForSafeDeletion(indexPath: indexPath)
completionHandler(true)
}
deleteAction.image = UIImage(systemName: "trash")
deleteAction.backgroundColor = .systemRed
let configuration = UISwipeActionsConfiguration(actions: [deleteAction])
return configuration
}
func alertForSafeDeletion(indexPath: IndexPath) {
impactFeedbackGenerator?.impactOccurred()
let alert = UIAlertController(title: nil, message: "정말 기록을 삭제할까요?", preferredStyle: .alert)
let yesAction = UIAlertAction(title: "네", style: .default) { _ in
let context = CoreDataStack.shared.managedObjectContext
let date = self.recordsByDate[indexPath.section][indexPath.row].createdDate ?? Date()
var calendar = Calendar.current
calendar.timeZone = NSTimeZone.local
context.delete(self.recordsByDate[indexPath.section][indexPath.row])
CoreDataStack.shared.saveContext()
self.recordsByDate[indexPath.section].remove(at: indexPath.row)
self.listTableView.deleteRows(at: [indexPath], with: .fade)
if self.recordsByDate[indexPath.section].count == 0 {
var matchingDate = [FinalDate]()
let fetchRequest = FinalDate.fetchRequest()
let dateFrom = calendar.startOfDay(for: date)
let dateTo = calendar.date(byAdding: .day, value: 1, to: dateFrom) ?? Date()
let fromPredicate = NSPredicate(format: "%@ <= %K", dateFrom as NSDate, #keyPath(FinalDate.creationDate))
let toPredicate = NSPredicate(format: "%K < %@", #keyPath(FinalDate.creationDate), dateTo as NSDate)
let datePredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [fromPredicate, toPredicate])
fetchRequest.predicate = datePredicate
do {
matchingDate = try context.fetch(fetchRequest)
} catch { print("context Error") }
if matchingDate.count > 0 {
context.delete(matchingDate[0])
}
self.recordsByDate.remove(at: indexPath.section)
self.dateSections.remove(at: indexPath.section)
self.onlyDateStr.remove(at: indexPath.section)
self.listTableView.deleteSections([indexPath.section], with: .fade)
self.showEmptyMessage()
self.calendarCalculation()
}
self.calendarView.reloadData()
CoreDataStack.shared.saveContext()
feedbackGenerator?.notificationOccurred(.success)
}
alert.addAction(yesAction)
let noAction = UIAlertAction(title: "아니오", style: .cancel) { _ in
impactFeedbackGenerator?.impactOccurred()
}
alert.addAction(noAction)
present(alert, animated: true, completion: nil)
}
}
'iOS 개발 > UIKit' 카테고리의 다른 글
[Auto Layout] Multiplier(2) (0) | 2021.12.22 |
---|---|
[Auto Layout] Multiplier(1) (0) | 2021.12.21 |
[Auto Layout] Equal Constraints에 대해서 (0) | 2021.12.20 |
[UIGestureRecognizer] tableview와 함께 사용하기 (0) | 2021.11.29 |
[UITextView] 줄 수, 글자 수 제한 (0) | 2021.11.22 |
[UIView] 정말 예쁜 blur Effect (0) | 2021.11.21 |
[Swift] App 첫 로딩을 감지하는 법 (first loading detection) (0) | 2021.11.20 |
[Swift] 앱 안에서 메일 보내기 (0) | 2021.11.20 |