MVP 중간 점검이 끝나고, 지금까지 새로운 일기를 작성, 수정, 삭제를 한다거나 사용자가 로그인, 로그아웃, 회원탈퇴를 하게 될 경우 View의 데이터를 리로드하는 시점을 ViewWillApear
에 때려박아놨었다. 그러다 보니, 리로드는 정말 기똥차게 처리하지만, 쓸데없이 불필요하게 데이터를 리로드하는 경우가 많아졌고, 일기의 갯수가 늘어날수록, 앱이 무거워지는 현상을 야기하게 되었다. 그래서 데이터를 로드하는 시점을 변경하는 작업이 필요했다.
일기는 일기를 작성, 수정, 삭제 시에만 데이터 리로드가 필요하다. 그렇다는 건, 작성 완료 버튼을 누르거나, 수정 버튼을 눌러서 일기 데이터가 업데이트 되거나, 삭제 버튼을 눌러 데이터가 삭제가 되는 경우이다. 이럴 경우에 View에서는 데이터를 리로드하여 반영을 시켜줘야 한다. 그렇다면 어떤 방식으로 VC에 전달해주는 게 좋을까?
우선, 데이터가 리로드 될때, 추가적인 View Component의 요소가 바뀌지 않고, 오로지 일기 데이터만 리로드를 해달라고 부탁하면 되는 상황이기에 1대1 통신만으로도 충분하다. 또한 다른 새로운 VC가 추가되고 해당 VC에서도 써야하는 상황에서 유연하게 대처 가능한 방식을 써야한다고 판단했다.
그래서 Delegate 패턴을 쓰기로 결정했다.
Delegate 패턴을 사용하면 일기 작성 또는 수정 화면이 일기 목록 화면에 대한 명확한 참조를 갖게 되어, 변경된 데이터를 직접 전달할 수 있다. 이는 데이터 흐름을 추적하기 쉽게 하며, 누가 데이터를 전달하는지 명확하게 한다. 또한, 작성 또는 수정된 일기 내용을 목록 화면에 바로 반영할 수 있어, 사용자 경험을 개선한다.
protocol DiaryUpdateDelegate: AnyObject {
func diaryDidUpdate()
}
// WriteDiaryVC에서
// 일기 작성하는 View에서 작성, 수정이 함께 일어난다
weak var delegate: DiaryUpdateDelegate?
func createAndUploadDiaryEntry(with title: String, content: String, dateString: String, imageUrls: [String] = []) {
let newDiaryEntry = DiaryEntry(
title: title,
content: content,
dateString: dateString,
emotion: selectedEmotion,
weather: selectedWeather,
imageURL: imageUrls
)
// DiaryManager를 사용해 FireStore에 저장
diaryManager.addDiary(diary: newDiaryEntry) { [weak self] error in
guard let self = self else { return }
self.isSavingDiary = false // 성공, 실패 여부를 떠나서 저장 시도가 완료되었으므로 변수 초기화
if let error = error {
// 에러처리
print("Error saving diary to Firestore: \(error.localizedDescription)")
} else {
// 에러가 없다면, 화면 닫기
self.dismiss(animated: true, completion: nil)
// delegate 설정하여 데이터 리로드
self.delegate?.diaryDidUpdate()
}
}
}
// CalendarVC에서
//MARK: - 일기 데이터 수정 시, View Reload
extension CalendarVC: DiaryUpdateDelegate {
func diaryDidUpdate() {
loadDiaries()
//데이터를 firebase에서 리로드하여 View를 업데이트 해주는 메서드
}
}
@objc private func tabWriteDiaryBTN() {
let writeDiaryVC = WriteDiaryVC()
writeDiaryVC.delegate = self
writeDiaryVC.modalPresentationStyle = .automatic
self.present(writeDiaryVC, animated: true)
}
self를 delegate에 할당함으로써, 현재 인스턴스(즉, self가 가리키는 인스턴스)가 writeDiaryVC의 대리자(delegate) 역할을 수행하게 된다. 이는 writeDiaryVC가 일기 작성, 수정, 저장 등의 특정 작업을 완료했을 때, 이에 대한 응답을 처리하기 위한 메서드를 현재 클래스에서 구현하고 호출할 수 있음을 의미한다.