Post

SwiftUI: @Binding을 지원하지 않는 뷰의 강제 리프레시

SwiftUI: @Binding을 지원하지 않는 뷰의 강제 리프레시

SwiftUI에서 @Binding을 지원하지 않는 뷰의 강제 리프레시

parametersParameterRow가 바인딩(Binding)을 사용하지 않고 있다면, SwiftUI는 내부 값이 바뀌더라도 해당 뷰(HStack)를 자동으로 업데이트하지 않습니다. 따라서 Randomize 버튼을 눌러도 뷰가 갱신되지 않는 문제가 발생합니다.

해결 방법: id 값을 바꿔서 뷰 강제 갱신

HStack 전체에 .id(...)를 주어 SwiftUI가 해당 뷰를 다른 것으로 인식하도록 하면 뷰 전체가 강제로 다시 그려집니다.

1
@State private var refreshID = UUID()

그 다음, HStack.id(refreshID)를 적용합니다:

1
2
3
4
5
6
HStack {
  ForEach(conductor.voc.parameters.indices, id: \.self) {
    ParameterRow(param: conductor.voc.parameters[$0])
  }
}
.id(refreshID) // <- 이게 핵심

그리고 Randomize 버튼에서 refreshID를 갱신해주면 SwiftUI는 뷰 전체를 새로 렌더링합니다:

1
2
3
4
5
6
7
8
Button("Randomize") {
  conductor.voc.frequency = AUValue.random(in: 0...2000)
  conductor.voc.tonguePosition = AUValue.random(in: 0...1)
  conductor.voc.tongueDiameter = AUValue.random(in: 0...1)
  conductor.voc.tenseness = AUValue.random(in: 0...1)
  conductor.voc.nasality = AUValue.random(in: 0...1)
  refreshID = UUID() // 강제 갱신 트리거
}

대안 (권장): Binding을 지원하도록 구조 수정

  • VocalTract.parameters@Published var 배열이면 @Binding으로 넘길 수 있습니다.
  • ParameterRow(param: Binding<NodeParameter>)처럼 정의하고, 수정 가능하게 만들 수도 있습니다.

하지만 외부 라이브러리이거나 구조를 못 바꾸는 경우에는 .id(UUID()) 방식이 가장 확실하고 간단한 방법입니다.


결론

parametersBinding을 지원하지 않더라도 HStack.id(refreshID)를 설정하고 UUID()를 변경하는 방식으로 뷰를 강제로 새로 그리게 만들 수 있습니다.

This post is licensed under CC BY 4.0 by the author.