이전 글에서 언급했듯이 일기를 생성하고 tableView에 표시가 되는 상황에서 수정과 삭제 기능을 넣기 위해 새로 DetailVC를 만들어서 MainVC에 연결을 해야했습니다.
알다시피 tableViewCell은 버튼이 아닙니다. 즉 Action을 통해 Segue로 화면 전환을 할 수가 없습니다. (ctrl키로 다른 VC로 연결하려고 해도 안됩니다..)
구글링을 통해서 해결 방법을 찾을 수 있었는데 UITapGestureRecognizer를 이용한 방법이었습니다.
그래서 UITableViewCell를 커스텀한 커스텀 셀에 UITapGestureRecognizer를 사용해보았습니다. UITapGestureRecognizer는 UIGestureRecognizer를 상속받았으며 제스쳐의 변경이 감지되면 대상 객체에 작업 메시지를 보내는 클래스입니다.
import UIKit
class DiaryDetailViewController : UIViewController {
@IBOutlet weak var date: UILabel!
@IBOutlet weak var emotion: UILabel!
@IBOutlet weak var content: UILabel!
var dateText = ""
var emotionText = ""
var contentText = ""
override func viewDidLoad() {
super.viewDidLoad()
date.text = dateText
emotion.text = emotionText
content.text = contentText
}
@IBAction func backBtnPushedEvent(_ sender: Any) {
self.presentingViewController?.dismiss(animated: true)
}
}
일단 새로운 VC를 생성했습니다.
간단하게 날짜, 기분, 내용 Text Label과 돌아가기 버튼을 만들었습니다.
viewDidLoad에서 이전 컨트롤러로부터 전달 받은 데이터를 입력시킵니다.
그리고 저는 이 VC를 나중에 인스턴스화 하기 위해서 identifier를 diaryDetailViewController으로 입력했습니다.
그리고 뒤로가기 버튼을 눌렀을 때 액션인 backBtnPushedEvent를 만들었습니다.
self.presentingViewController?.dismiss(animated: true)
: presentingViewController는 이 VC를 인스턴스화하고 present 명령을 한 VC, 여기서는 MainVC가 됩니다. 그 VC에서 dismiss를 통해서 다시 mainVC로 돌아오게 합니다.
import UIKit
class DiaryTableViewCell: UITableViewCell{
var mainVC: UIViewController?
var row: String?
@IBOutlet weak var diaryTableViewCellDate: UILabel!
@IBOutlet weak var diaryTableViewCellEmotion: UILabel!
@IBOutlet weak var diaryTableViewCellContent: UILabel!
override func awakeFromNib() { //Instance 화 될 때
super.awakeFromNib()
let tapGesture = UITapGestureRecognizer(target:self, action: #selector(cellTabEvent(sender:)))
self.addGestureRecognizer(tapGesture)
}
@objc func cellTapEvent(sender: UITapGestureRecognizer) {
guard let vc = mainVC?.storyboard?.instantiateViewController(withIdentifier: "diaryDetailViewController") as? DiaryDetailViewController else {return}
vc.modalTransitionStyle = .coverVertical
vc.modalPresentationStyle = .fullScreen
vc.dateText = diaryTableViewCellDate.text!
if let emotion = diaryTableViewCellEmotion.text {
vc.emotionText = emotion
}
vc.contentText = diaryTableViewCellContent.text!
mainVC?.present(vc, animated: true)
}
}
override func awakeFromNib() {
super.awakeFromNib()
let tapGesture = UITapGestureRecognizer(target:self, action: #selector(cellTapEvent(sender:)))
self.addGestureRecognizer(tapGesture)
}
awakeFromNib는 이 cell이 인스턴스화 될 때 호출되는 메서드입니다.
tableView가 cell을 하나하나 인스턴스화 할 때 각 cell에서 호출된다고 보았습니다.
let tapGestureUITapGestureRecognizer(target:self, action: #selector(cellTapEvent(sender:)))
@objc func cellTapEvent(sender: UITapGestureRecognizer) {
guard let vc = mainVC?.storyboard?.instantiateViewController(withIdentifier: "diaryDetailViewController") as? DiaryDetailViewController else {return}
vc.modalTransitionStyle = .coverVertical
vc.modalPresentationStyle = .fullScreen
vc.dateText = diaryTableViewCellDate.text!
if let emotion = diaryTableViewCellEmotion.text {
vc.emotionText = emotion
}
vc.contentText = diaryTableViewCellContent.text!
mainVC?.present(vc, animated: true)
}
guard let vc = mainVC?.storyboard?.instantiateViewController(withIdentifier: "diaryDetailViewController") as? DiaryDetailViewController else {return}
: 스토리보드에서 identifier가 diaryDetailViewController에 해당하는 VC를 인스턴스화합니다. vc.dateText = diaryTableViewCellDate.text!
if let emotion = diaryTableViewCellEmotion.text {
vc.emotionText = emotion
}
vc.contentText = diaryTableViewCellContent.text!
date, emotion, content의 정보들을 인스턴스화 시킨 VC의 변수에 저장시켰습니다. (emotion은 옵셔널이라 바인딩을 사용했습니다.)
각 IBOutlet의 text에 입력하면 되지 않겠냐는 생각이 있었지만 (vc.date = diaryTableViewCellDate.text!
)
아마 오류가 나지 않을까 싶습니다. 왜냐면 present 명령어가 실행되지 않았을 때, 그러니까 view가 생성되지 않았을때 접근하기 때문입니다.
다음 글은 삭제 기능을 다루게 되지 않을까 싶습니다. 이 기능을 구현하기 위해서 아마 cell마다 번호를 지정하고 DetailDiaryVC에서 삭제를 누르면 ViewModel에서 번호에 해당하는 일기를 삭제하고 MainVC에서 tableView를 reloadData 해야하지 않을까 싶은데.. 이게 또 나중에 데이터베이스를 구축한다면 다시 코드를 변경 해야하니까 뭘 먼저해야할지 고민이 듭니다..