Control and respond to the flow of data and changes within your app’s models.
번역 ) 앱 모델 내에서 데이터 흐름 및 변경 사항을 제어하고 응답합니다.
SwiftUI는 UI 설계의 선언적 접근 방식을 제공합니다. 뷰 계층을 구성할 때 데이터 종속성 또한 나타냅니다. 데이터가 변경된 경우 영향을 받는 UI 부분을 자동 업데이트 합니다. 기존 뷰 컨트롤러가 수행하던 대부분의 작업을 자동으로 수행합니다.
SwiftUI는 State변수와 Bindings과 같은 도구를 제공하여, 앱의 데이터를 UI에 연결합니다. 이러한 도구들은 복잡한 양의 로직을 줄일 수 있기 때문에, 앱의 모든 데이터 정보를 단일 진실 정보(Single Source Of Truth)로 유지하는 것을 돕습니다.
Encapsulate view-specific data within your app’s view hierarchy to make your views reusable.
번역 ) 앱의 보기 계층 내에 보기별 데이터를 캡슐화하여 보기를 재사용할 수 있습니다.
View 간에 공유되는 단일 진실 정보(SSOT)를 확립하기 위해 데이터가 필요한 View 최소 공통 조상(Least Common Ancestor)에 데이터를 State로 저장합니다. Swift 속성을 통해 읽기전용으로 제공하거나, Binding으로 State에 대한 양방향 커넥션을 만듭니다. SwiftUI는 데이터의 변경을 감시하고 필요에 따라, 영향을 받는 View를 업데이트 합니다.
State 변수의 Life Cycle은 View의 Life Cycle을 반영하므로, 영구 저장에 State 속성을 사용하지 마세요. 대신에, 버튼의 하이라이트 State, 필터 세팅들 또는 현재 선택된 리스트 아이템과 같은 UI에만 영향을 주는 영구 State를 관리하기 위해 사용합니다. 시제품 제작 동안 앱 데이터 모델을 변경할 준비가 되기 전에, 이러한 종류의 storage가 편리하다는 것을 알 수도 있습니다.
View 에서 수정할 수 있는 데이터를 저장해야 하는 경우 State로 래핑하여 변수를 선언합니다.
예시 ) 팟캐스트 플레이어 뷰 내에 isPlaying Boolean을 만들어 팟캐스트가 실행 중인 시기를 추적할 수 있습니다.
struct PlayerView: View {
@State private var isPlaying: Bool = false
var body: some View {
// ...
}
}
Property를 State로 래핑하면 SwiftUI는 저장소 아래에서 관리합니다. View는 Property 이름을 사용하여 State의 wrappedValue Property에 있는 데이터를 읽고 씁니다. Value를 변경하면 SwiftUI는 View에 영향을 받는 부분을 업데이트 합니다.
Button(action: {
self.isPlaying.toggle()
}) {
Image(systemName: isPlaying ? "pause.circle" : "play.circle")
}
Private로 제한하면, 변수를 선언하는 View 계층에 변수가 캡슐화된 상태로 유지됩니다.
View에서 수정하지 않는 데이터를 뷰에 제공하려면 표준 Swift Property을 선언합니다.
예시 ) 팟캐스트 플레이어를 확장하여 에피소드 제목과 쇼 이름의 문자열을 포함하는 입력 구조체를 가질 수 있습니다.
struct PlayerView: View {
let episode: Episode // The queued episode.
@State private var isPlaying: Bool = false
var body: some View {
VStack {
// Display information about the episode.
Text(episode.title)
Text(episode.showTitle)
Button(action: {
self.isPlaying.toggle()
}) {
Image(systemName: isPlaying ? "pause.circle" : "play.circle")
}
}
}
}
Child View에서 State의 접근 공유가 필요하다면 Binding으로 래핑한 Property를 Child에서 선언해야 합니다. Binding은 기존 스토리지에 대한 참조를 표시하먀, 기본 데이터에 대한 단일 진실 정보(SSOT)를 유지합니다.
예시 ) 팟캐스트 플레이어 View 버튼을 PlayButton이라는 Child View로 리팩터링하면 isPlaying Property에 Binding을 제공할 수 있습니다.
struct PlayButton: View {
@Binding var isPlaying: Bool
var body: some View {
Button(action: {
self.isPlaying.toggle()
}) {
Image(systemName: isPlaying ? "pause.circle" : "play.circle")
}
}
}
위와 같이 Binding으로 래핑된 값은 State와 마찬가지로 Property을 직접 참조하여 읽고 씁니다. 그러나 State Property과는 달리 Binding에는 자체 스토리지가 없습니다. 대신 다른 곳에 저장된 State Property을 참조하고 해당 storage에 대한 양방향 연결을 제공합니다.
PlayButton을 인스턴스화하는 경우 Parent View에서 선언된 대응하는 State 변수에 $를 부가하여 Binding을 제공합니다.
struct PlayerView: View {
var episode: Episode
@State private var isPlaying: Bool = false
var body: some View {
VStack {
Text(episode.title)
Text(episode.showTitle)
PlayButton(isPlaying: $isPlaying) // Pass a binding.
}
}
}
$는 projectedValue으로 래핑된 Property을 요청합니다. 이 값은 기본 스토리지에 대한 Binding입니다. 마찬가지로 $를 사용하여 Binding에서 Binding을 얻을 수 있습니다. 이것에 의해, 임의의 수의 View 계층에 Binding을 건네줄 수 있습니다.
State 변수 내에서 범위 지정 값에 대한 Binding을 가져올 수도 있습니다. 예시 ) 플레이어의 Parent View에서 에피소드를 State 변수로 선언하고 에피소드 구조체에도 토글을 사용하여 제어할 isFavorite Bool이 포함되어 있는 경우 $episode.isFavorite를 참조하여 에피소드 즐겨찾기 상태에 대한 Binding을 얻을 수 있습니다.
struct Podcaster: View {
@State private var episode = Episode(title: "Some Episode",
showTitle: "Great Show",
isFavorite: false)
var body: some View {
VStack {
Toggle("Favorite", isOn: $episode.isFavorite) // Bind to the Boolean.
PlayerView(episode: episode)
}
}
}
View State가 변경되면 SwiftUI는 영향을 받는 View를 즉시 업데이트합니다. withAnimation(_:) 함수로 래핑 해 애니메이션을 실시하도록 지시합니다.
예시 ) isPlaying Bool에 의해 제어되는 Change를 애니메이션으로 만들 수 있습니다.
withAnimation(.easeInOut(duration: 1)) {
self.isPlaying.toggle()
}
.scaleEffect()
Image(systemName: isPlaying ? "pause.circle" : "play.circle")
.scaleEffect(isPlaying ? 1 : 1.5)
VStack {
Text(episode.title)
Text(episode.showTitle)
PlayButton(isPlaying: $isPlaying)
}
.background(isPlaying ? Color.green : Color.red) // Transitions with animation.
A property wrapper type that can read and write a value managed by SwiftUI.
번역 ) SwiftUI에서 관리하는 값을 읽고 쓸 수 있는 Property 래퍼 유형입니다.@frozen @propertyWrapper struct State<Value>