Swift 일기장 개발 일기 4 (tableViewCell 삭제, alertVC)

송민준·2023년 1월 3일
0

일기장 개발 일기

목록 보기
4/11

목표

일기장에 일기를 생성했으니 삭제하는 기능도 있어야 하죠. 그래서 tableViewCell을 삭제하는 기능을 넣어보려고 합니다. 저번 글에서 언급했다시피 데이터베이스를 먼저할까, 삭제 기능을 먼저할까 고민했었는데 사실 생각해보니까 ViewModel만 수정하면 될 일이라서 삭제 먼저 구현을 해보았습니다.

Idea

먼저 코딩하기 전에 생각해보았는데
1. 일기를 삭제하기 위해서는 각 일기의 index가 있어야 삭제가 용이합니다.
2. 또한 삭제는 신중이 필요한 동작이므로

이런식으로 삭제 알림을 만들어야합니다.
3. ViewModel에서 삭제 메서드를 만들어야합니다. 고민했던 것이 있는데 DiaryListViewModel은 현재 mainVC에서 구성하는 객체인데 이를 SingleTon 패턴으로 만들어서 다른 VC에서 사용하면 되지 않을까란 고민을 했습니다.
-> StackOverflow에 검색했는데 응답은 하면 안된다. 라고 합니다. 그 이유는 ViewModel은 수명이 그리 길지 않아야 하기 때문이라고 합니다. MVVM에서 주어진 ViewModel의 수명은 사용자가 창을 열고 변경을 완료하는 만큼의 길이라고 합니다. (https://stackoverflow.com/questions/6188584/viewmodel-and-singleton-pattern)

Coding

1.

DiaryTableViewCell

class DiaryTableViewCell: UITableViewCell{
    
    var index: Int?
    
    ...
    
    @objc func cellTabEvent(sender: UITapGestureRecognizer) {
        guard let vc = mainVC?.storyboard?.instantiateViewController(withIdentifier: "diaryDetailViewController") as? DiaryDetailViewController else {return}
        
        ...
        
        vc.index = index
        
        
        mainVC?.present(vc, animated: true)
        
    }
    ...
}
  • index: cell의 인덱스 변수입니다.
  • vc.index = index: DiaryDetailVC에 index 값을 넘겨줍니다.

MainViewController

class MainViewController: UIViewController, SendDataDelegate, UITableViewDelegate, UITableViewDataSource {
    ...
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard let cell = tableView.dequeueReusableCell(withIdentifier: "diaryCell", for: indexPath) as? DiaryTableViewCell else {return UITableViewCell()}
        ...
        
        cell.index = indexPath.row
        
        return cell
    }
    ...
}
  • cell.index = indexPath.row: cell마다 tableView에서의 인덱스를 넘겨줍니다.

2.

class DiaryDetailViewController : UIViewController {
    ...
    @IBAction func deleteBtnPushedEvent(_ sender: Any) {
        let alertVC = UIAlertController(title:"알림", message: "정말로 삭제하시겠습니까?", preferredStyle: .actionSheet)
        alertVC.addAction(UIAlertAction(title:"아니오", style:.destructive, handler:{_ in print("No Clicked!")}))
        alertVC.addAction(UIAlertAction(title:"네", style:.cancel, handler:{
            _ in self.diaryCell?.deleteDiary(index: self.index)
            self.presentingViewController?.dismiss(animated:true)
        }))
        self.present(alertVC, animated: true)
    }
}
  • let alertVC = UIAlertController(title:"알림", message: "정말로 삭제하시겠습니까?", preferredStyle: .actionSheet): UIAlertController는 알림을 나타낼 때 주로 사용합니다. title, message, style을 따로 지정해줄 수 있습니다.
  • alertVC.addAction(UIAlertAction(title:"아니오", style:.destructive, handler:{_ in print("No Clicked!")})): UIAlertController에서 UIAertAction을 생성합니다. Action을 선택했을 때 어떤 작업을 할지 handler로 지정할 수 있습니다.
  • self.present(alertVC, animated: true)

3.

DiaryListViewModel

class DiaryListViewModel: NSObject{
    var diary: Diary!
    var diaryList: [Diary]!
    ...
    func deleteDiaryData(index:Int){
        diaryList.remove(at:index)
        
    }
}
  • diaryList.remove(at:index) : 삭제하는 cell의 index를 이용해서 diaryList에서 삭제합니다.

DiaryTableViewCell

protocol DeleteDiaryDelegate {
    func deleteDiary(index:Int) -> ()
}
class DiaryTableViewCell: UITableViewCell, DeleteDiaryDelegate{
    var mainVC: MainViewController?
    ...
    @objc func cellTabEvent(sender: UITapGestureRecognizer) {
        guard let vc = mainVC?.storyboard?.instantiateViewController(withIdentifier: "diaryDetailViewController") as? DiaryDetailViewController else {return}
        vc.diaryCell = self
        ...
    }
    func deleteDiary(index:Int){
        mainVC?.diaryListViewModel.deleteDiaryData(index: index)
        mainVC?.diaryListTableView.reloadData()
    }
}

cell은 MainVC를 가지고 있고 DiaryDetailVC의 alertVC의 Action에 따라 MainVC의 DiaryListViewModel의 deleteDiaryData를 사용하기 위해서 Delegate Pattern을 이용했습니다.

  • protocol DeleteDiaryDelegate, func deleteDiary(index:Int): ViewModel의 DiaryList의 요소를 삭제하고 tableView를 갱신합니다.

결과


제 나름 생각해본 아이디어로 구현을 해보았습니다. 더 나은 방법이 있다면 댓글로 알려주시고 수정해보려고 노력하겠습니다.
그리고 velog 마크다운도 연습해야겠습니다. 사진 삽입하는데 공간을 너무 차지해버리네요. 좀 더 글을 잘쓰도록 노력하겠습니다.

profile
개발자

0개의 댓글