SwiftUI의 View에는 onChange라는 함수가 modifier로 만들어져 있다.
DummyView()
.onChange(of: viewModel.publishedValue) { _ in
speakSomeText()
}
작동하는 방식은 대략 이렇다 of로 전달하는 변수의 값이 변하고 그 변수가 View에 자신이 변했다는것을 알리는 유형의 변수(State나 Published property를 갖는 변수)인 경우 그 변수의 값이 변할때마다 클로저의 값을 실행시킨다.
오늘은 이 onChange의 동작방식을 잘못이해하여 동작이 원활하게 되지 않았던것에 대해 작성하려고 한다.
먼저 나는 생각했을때 onChange함수에 of로 전달하는 변수의 값이 변할때만 클로저가 실행된다고 생각했다.
그런 생각으로 ARSessionDelegate 프로토콜을 사용하는 다른 ViewController에서 onChange에 전달하는 변수의 값을 변경해도 값이 같다면 클로저안의 내용이 잘 실행될거라고 생각했다.
하지만 결과는 예상과는 달랐다.
func session(_ session: ARSession, didAdd anchors: [ARAnchor]) {
for anchor in anchors {
if let viewModel = viewModel, !viewModel.publishedValue {
viewModel.check()
}
}
}
내가 처음에 작성한 코드는 대충 이런식의 코드에서 if let viewModel = viewModel, !viewModel.publishedValue 이 조건문을 추가하지 않은 상태였다. (여기에 나온 함수와 변수들의 이름은 실제 작성한 것과 다릅니다.)
check()함수는 이렇게 되어진 함수이다.
func check() {
publishedValue = true
}
내가 처음 생각한거에 대입해본다면 check함수가 계속 실행되더라도 publishedValue의 값은 처음에만 false에서 true로 변경되기 때문에 session함수가 계속 반복되더라도 onChange함수가 한번만 반응하여서 실행되고 speak이 함수가 정상적으로 동작하는줄 알았다.
하지만 speak함수가 제대로 동작하지 않았고 if let viewModel = viewModel, !viewModel.publishedValue 이 코드를 추가한다음 제대로 동작하는걸 보니 onChange함수는 일단 변수에 접근하면 클로져에 뭔가를 하는거 같다.
그래서 speak함수에서 tts에 접근하는 함수들이 계속 실행되고 OS에서 자동으로 onChange함수에서 실행되는것을 차단하여 제대로 tts가 구동되지 않은것같다..