Skip to content

[이준복] Data Flow Through SwiftUI ‐ @State, @Binding

junbok97 edited this page Jul 30, 2024 · 1 revision

UIKit에서 Data Flow

Swift UI가 나오기전 UIKit에서의 Data Flow는 보통 아래와 같았음

1

하나의 VC(PlayerViewController)에 하위 View(PlayerView, PlayButton)들이 있고

VC의 Model에서 하위 View들에게 값을 전달해주는게 일반적이었는데 여기서 동기화의 문제가 발생

PlayButton과 PlayerViewController의 isPlaying의 값이 동일해야 함

혹은 다른 다양한 View에서 같은 속성(isPlaying)을 사용한다면 같은 속성을 사용하는 View들의 isPlaying 값이 동일해야 함

즉 중복된 데이터들이 생기게 되고 어떤값이 진짜인지 알 수 없게 됨

그래서 이 문제들을 해결하기위해 다양한 아키텍쳐 및 디자인 패턴들이 등장하였고

결과적으로 View와 Model을 분리하고 Model을 한곳에서만 관리하여 View간의 동기화 문제를 해결하고자 하였음

SwiftUI에서 DataFlow

그래서 SwiftUI에선 새로운 Data Flow Tool들을 제공

SwiftUI는 UIKit과 다르게 VC가 없음 크게 뷰와 뷰의 상태정보만이 존재하는데

SwiftUI에선 뷰의 상태 프로퍼티를 보관하는 장소가 따로 있음

SwiftUI는 @State로 선언된 프로퍼티의 저장소를 관리

2
struct PlayerView: View {
    var isPlaying: Bool
    
    var body: some View {
          PlayerButton(isPlaying: isPlaying)
    }
}

struct PlayerButton: View {
    var isPlaying: Bool
}

PlayerView와 PlayerButton 둘 다 isPlaying이라는 프로퍼티가 필요해서 생기는 문제

  • 기존까지의 방식으론 isPlaying 프로퍼티는 두 View에 존재하는 문제
  • PlayerView의 isPlaying과 PlayerButton의 isPlaying 값을 동일하게 맞춰주려면 개발자가 별도의 로직을 구현
  • SwiftUI는 View들이 struct이기 때문에 내부에서 isPlaying의 값을 바꿔주려면 Mutating 키워드를 붙혀야하는 문제

이때 사용하는것이 바로 @State

3

PlayerView의 isPlaying 프로퍼티 앞에 @State 키워드를 붙이는 순간 isPlaying 프로퍼티는 Single Source of Truth이 되어 SwiftUI에서 관리

Use state as the single source of truth for a given value stored in a view hierarchy.

4

Single Source of Truth가 된 프로퍼티를 다른곳에서도 사용할 수 있게 해주는것이 @Binding

@Binding을 통해 @State로 Single Source of Truth가 된 프로퍼티 원본에 접근 가능

State 키워드가 붙은 프로퍼티의 prefix에 $를 추가하여 Binding

struct PlayerView: View {
    @State private var isPlaying: Bool
    
    var body: some View {
         PlayerButton(isPlaying: $isPlaying)
    }
}

struct PlayerButton: View {
    @Binding var isPlaying: Bool
}

SwiftUI는 상태프로퍼티의 값이 변경 되면 상태프로퍼티에 맞게 View가 업데이트가 되어야 한다는것을 알 수 있고

SwiftUI는 상태프로퍼티가 포함된 View 계층구조의 일부 View들을 업데이트

5

@State

6

SwiftUI에서 관리하는 값을 읽고 쓸 수 있는 property wrapper type

@State에 private 키워드를 붙이는것을 권장하고 있는데 외부에서 State 프로퍼티에 접근하지 못하게 해야

모든 스레드에서 State 프로퍼티의 값을 안전하게 변경할 수 있음

SwiftUI는 상태프로퍼티의 값이 변경 되면 상태프로퍼티에 맞게 View가 업데이트가 되어야 한다는것을 알 수 있고

SwiftUI는 상태프로퍼티가 포함된 View 계층구조의 일부 View들을 업데이트

struct PlayerView: View {
    @State private var isPlaying: Bool
}

7
8
9

@Binding

10

Single Source of Truth(State Property) 가 소유한 값을 읽고 쓸 수 있게 해주는 프로퍼티 랩퍼

State는 View내부에서 선언하는것과 달리 Binding은 상위 View로부터 전달받아서 사용

생성자를 통해 상위 View의 State 값을 주입받아야 하고 주입받을 상태프로퍼티의 이름에 prefix로 $표시를 붙혀 Binding

struct PlayerView: View {
    @State private var isPlaying: Bool
    
    var body: some View {
         PlayerButton(isPlaying: $isPlaying)
    }
}

struct PlayerButton: View {
    @Binding var isPlaying: Bool
}
11 12

요약

  • SwiftUI는 View와 View의 State관리가 중요
  • SwiftUI는 @State 를 통해 Single Source of Truth를 나타낼수 있음
  • SwiftUI는 @State 로 선언된 상태 프로퍼티의 저장소를 관리
  • @Binding 을 통해 **Single Source of Truth(State Property)**에 접근 가능
  • @Binding 을 할때는 @State 로 선언된 상태 프로퍼티의 이름에 prefix로 $표시를 추가해 사용
  • SwiftUI는 State프로퍼티가 변하면 State프로퍼티가 포함된 View 계층구조의 일부 View들을 업데이트

참고

Clone this wiki locally