Combine
과 KVO(Key-Value Observing)
를 각각 활용하여
key-value
쌍으로 디바이스에 데이터를 저장하는 기능을 제공하는 인터페이스인 UserDefaults
의 특정 Key의 변화를 비동기적으로 반영하는 방법을 알아보자!
먼저, 사용하고자 하는 key
의 이름(link
)과 type(String
)을 지정하여 Extension
을 작성해준다.
(여기서 link
는 UserDefaults의 key path로 쓰인다!)
extension UserDefaults {
@objc var link: String {
get {
return string(forKey: "Link") ?? ""
}
set {
set(newValue, forKey: "Link")
}
}
}
앞서 만든 key path(\.link
)를 publisher로 활용하여 구독 관계를 성립한다.
handleEvents
내부에 변화가 감지되었을 때 실행할 함수를 작성해주면 된다.
UserDefaults.standard
.publisher(for: \.link)
.handleEvents(receiveOutput: { link in
print("---> link = \(link)")
self.updateErrorMessage(isError: false, message: "이메일 인증 완료!")
})
.sink { _ in }
.store(in: &subscriptions)
let link = "[link 값]"
UserDefaults.standard.link = link
🌱 KVO
- 객체의 프로퍼티의 변경사항을 다른 객체에 알리기 위해 사용하는 코코아 프로그래밍 패턴
- Model과 View와 같이 논리적으로 분리된 파트간의 변경사항을 전달하는데 유용하다.
- NSObject를 상속한 클래스에서만 KVO를 사용할 수 있다.
변화된 UserDefaults value는
defaults
를 changeHandler 클로저의 첫번째 파라미터로 선언한 경우,
defaults.[key path]
로 접근할 수 있다.
var observer: NSKeyValueObservation?
init() {
observer = UserDefaults.standard.observe(\.link, changeHandler: { defaults, value in
let link = defaults.link
// print("---> link: \(link)")
if !link.isEmpty {
self.updateErrorMessage(label: self.emailErrorLabel, isError: false, message: "이메일 인증 완료!")
self.emailAuthCompleted = true
} else {
self.emailErrorLabel.text = ""
self.emailAuthCompleted = false
}
})
}
class가 종료될 때, observer를 비활성화하여 메모리 누수를 방지해야 한다.
deinit {
observer?.invalidate()
}
참고자료