Open HJLEE-22 opened 2 years ago
시작 : Observer / Subscriber 프로토콜 생성
Observer / Subscriber 코드
protocol Observer {
func update<T>(updatedValue: T)
}
protocol Subscriber {
var observer: (any Observer)? { get set }
mutating func unSubscribe(observer: (any Observer)?)
mutating func subscribe(observer: (any Observer)?)
func notify<T>(updatedValue: T)
}
Model / ViewModel / View(ViewController) 역할
View
// View는 VC에서 Model을 받아 View를 configure한다.
// model을 받을때마다 데이터가 변동되야 하니까 didset.
var weatherModel: WeatherModel? {
didSet {
if let weatherModel = weatherModel {
self.configureUI(weatherModel)
}
}
}
ViewModel
Subscriber 프로토콜 채택. 프로토콜의 메서드들에 기본값 제공.
// 서브스크라이버 프로토콜 초기화. 기본값 넣어주기.
extension WeatherViewModel: Subscriber {
func unSubscribe(observer: (Observer)?) {
self.observer = nil
}
func subscribe(observer: (any Observer)?) {
self.observer = observer
}
func notify<T>(updatedValue: T) {
observer?.update(updatedValue: updatedValue)
}
}
VC와 연결할 observer 객체 생성.
// VC를 받을 옵저버 객체 만들어놓기 (일종의 델리게이트 프로퍼티)
// 질문 : 구지 internal로 선언하는 이유는 무엇인가요?
// 질문 : any 가 무엇인가요...?
internal var observer: (any Observer)?
ModelDataManager로부터 Model을 받아와 model객체를 초기화.
이렇게 초기화한 model 값을 subscriber 프로토콜의 notify를 통해 전달
private var todayWeatherModel: WeatherModel = WeatherModel() {
didSet {
notify(updatedValue: [Day.today: todayWeatherModel])
}
}
// 오늘 날씨
DispatchQueue.global().async { [weak self] in
guard let selfRef = self else { return }
WeatherService.shared.fetchWeatherData(dayType: Day.today,
date: DateCalculate.yesterdayDateString,
time: "2300",
nx: selfRef.nx,
ny: selfRef.ny) { result in
switch result {
case .success(let weatherModel):
selfRef.todayWeatherModel = weatherModel
case .failure(let error):
print("오늘 날씨 불러오기 실패", error.localizedDescription)
}
}
}
ViewController
VM에서 받아온 Model을 View에 던져주는 역할
옵저버 프로토콜을 채택하고, update 함수에 전달하기 원하는 데이터 타입 구성.
(각) View에 데이터를 전달한다.
// 이렇게 VC가 옵저버가 됬다면, 유일하게 할 일은 뷰에 데이터 모델을 전달하는 것...
// 즉, View와 model의 연결은 VC에서...
// 그런데 Model은 VM에서 만들었는데 왜 이렇게 하느냐?
// VC/View에서 Model객체를 초기화(생성)하지 않기 위해서!! 이렇게 구지구지 돌고돌아 가는것!
// 그러고보면 VC는 Model이랑 View와 VM 모두를 연결하고 있네...?
// VC의 관계 정리 :
// 1. VC는 스스로 옵저버가 되어, VM을 섭스크라이브 한다. 여기서 VM이 초기화하는 Model을 받아온다.
// 2. VC는 Model을 초기화하지 않고, VM을 통해 받아와 View에 전달한다.
extension WeatherViewController: Observer {
func update<T>(updatedValue: T) {
guard let value = updatedValue as? [Day: WeatherModel] else { return }
DispatchQueue.main.async { [weak self] in
switch value.first?.key {
case .today:
self?.mainView.todayWeatherView.weatherModel = value[.today]
case .tomorrow:
self?.mainView.tomorrowdayWeatherView.weatherModel = value[.tomorrow]
case .yesterday:
self?.mainView.yesterdayWeatherView.weatherModel = value[.yesterday]
case .none:
break
}
}
}
}
VM에게 자신이(해당 VC가) 옵저버임을 알려야 함
// VC는 VM에게 알리기만 한다! VM이 알아서 다 해먹도록!
// 그래서 VC에선 VM의 섭스크라이브만 해놓고, 옵저버를 VC 자신으로 등록.........
var viewModel: WeatherViewModel! {
didSet {
viewModel.subscribe(observer: self)
}
}
해결하고자 하는 주제에 대해 설명 해 주세요.
위 주제를 해결할 수 있는 방안으로는 어떤 것이 있나요?
어떤 이슈와 연관성이 있나요?
다음 작업들이 진행되어야 합니다.
참고 사항
참고 할만한 문서나, 서비스의 링크를 적어 주세요.