소피it블로그
[SwiftUI] State 정리 본문
https://developer.apple.com/documentation/swiftui/state
스위프트UI에 의해 관리되는 프라퍼티 래퍼 타입으로, 값을 읽고 쓸 수 있음
스위프트UI는 state로 선언한 프라퍼티의 저장을 관리한다. 해당 값이 변경되면 스위프트UI는 그 값에 의존하는 뷰 위계의 일부분을 갱신한다. 뷰 위계질서 내부에 저장된 한 값에 대한 유일한 source of truth로써 state를 사용하라.
State 인스턴스는 그 자체로서 값은 아니다. 이는 값을 읽고 쓰는 수단에 해당한다. state의 값에 접근하기 위해서는 프라퍼티명을 부르면 되는데, 그 결과로써 wrappedValue 프라퍼티 값이 반환된다. 예를 들면 PlayButton뷰 내부에서 isPlaying state 프라퍼티를 읽고 업데이트 하려면 해당 프라퍼티를 직접적으로 부르면 된다.
struct PlayButton: View {
@State private var isPlaying: Bool = false
var body: some View {
Button(isPlaying ? "Pause" : "Play") {
isPlaying.toggle()
}
}
}
자식 뷰에게 state 프라퍼티를 전달할 경우 스위프트UI는 부모 뷰에서 값이 변할 때마다 자식 뷰를 업데이트하지만, 자식 뷰는 값을 변경할 수 없다. 자식 뷰가 저장된 값을 변경할 수 있도록 하기 위해서는 Binding을 사용하여 전달하라. state의 projectedValue에 접근함으로써 state 값에 바인딩을 가져올 수 있는데, 이는 프라퍼티명 앞에 달러 기호($)를 적어줌으로써 가능하다.
예를 들어, 위의 예시에서 플레이 버튼에서 isPlaying state를 제거하는 대신 버튼이 state에 바인딩을 취할 수 있게 해줄 수 있다.
// 자식 뷰
struct PlayButton: View {
@Binding var isPlaying: Bool
var body: some View {
Button(isPlaying ? "Pause" : "Play") {
isPlaying.toggle()
}
}
}
그런 후에 state를 선언하고 state에 대하여 바인딩을 생성하는 player 뷰를 달러 기호를 사용하여 정의해줄 수 있다.
// 부모 뷰
struct PlayerView: View {
var episode: Episode
@State private var isPlaying: Bool = false
var body: some View {
VStack {
Text(episode.title)
.foregroundStyle(isPlaying ? .primary : .secondary)
PlayButton(isPlaying: $isPlaying) // Pass a binding.
}
}
}
뷰 위계질서 내에서 특정 뷰를 인스턴스화하는 상황에서는 그 뷰의 state 프라퍼티를 이니셜라이징 하지 마라. 이는 스위프트UI가 제공하는 저장 관리와 충돌이 일어날 수 있기 때문이다. 이 충돌을 피하기 위해서는 state를 항상 private로 선언하고, 뷰 위계질서 내에서 그 값에 접근해야하는 뷰들 중 가장 상위의 뷰에 위치시키도록 하라. 그런 후 그 state에 접근해야 하는 자식 뷰들과 공유하라. 공유는 읽기 전용 접근을 위해 직접적으로 할 수도 있고, 읽고 쓰기 접근을 위한 바인딩으로 공유할 수도 있다.
state 프라퍼티는 모든 스레드에서 안전하게 mutate할 수 있다.
'개발_iOS > 스위프트UI' 카테고리의 다른 글
[SwiftUI] 앱에서 모델 데이터 관리하기 - 공식 문서 번역 (0) | 2022.08.12 |
---|---|
[SwiftUI] ObservedObject 정리 (0) | 2022.08.12 |
[SwiftUI] Binding 정리 (0) | 2022.08.11 |
[SwiftUI] 스위프트 UI 컴포넌트 정리 (0) | 2022.05.01 |