-
SwiftUI) State, Binding wrapperSwiftUI/Basic Property Wrappers 2021. 9. 13. 17:02
SwiftUI 로 개발을 하다보면 다음과 같은 Property Wrapper 가 아주 많이 보이게 되는데,
이번 포스트에서는 매우매우 빈번히 쓰이는 wrapper 중에서 @State, @Bind 대해서 알아보도록 하겠습니다.
@State
SwiftUI 에서 View 들은 Struct 이고, Struct 는 value type 으로, 값을 바꾸는게 허용되지 않아요 ..
SwiftUI 에서는 값들을 바꿀 수 있게 해주기 위해 @State property Wrapper 를 제공합니다.
struct ContentView: View { var testString = "" var body: some View { Button(action: { // testString = "asd" Cannot assign to property: 'self' is immutable }, label: { Text("Button") }) } }
Structure 내에서 변수를 바꾸려고 하면 'Cannot assign to property: 'self' is immutable 이라는 에러메시지를 띄우게되죠 .
이때, @State 를 변수에 씌워주게되면 struct 밖의 SwiftUI 가 관리하는 shared Storage 로 storage를 옮겨서 저장하게 됩니다.
이렇게 되면 SwiftUI는 @State 로 씌워진 data 를 그대로 유지하면서 struct 를 마음껏 destroy, recreate 할 수 있게 돼요.
@State 가 씌워진 structs 는 간단한 type 으로 되는게 좋아요. (String, Int 등) 그리고 다른 Views 과는 공유되지 않습니다.
만약 다른 Views 과 어떤 값을 공유하고싶다면, @ObservableObject 또는 @EnvironmentObject 와 함께 쓰시게 될거에요.
Apple 은 @State 의 특성을 다시 스스로 생각해보기 위해 private keyword 를 붙이길 권장합니다. ( 안붙여도 상관 없지만 권장)
@State private var username = ""
Tip:
Reference types 의 값을 track 하기 위해 @State 를 붙이셔도 되지만, 값들이 변할 때 notified 되지는 않아요.
이런 방식은 Observable protocol 을 conform 하지 않는 classes 에 대해 사용하시면 아주아주 유용합니다.
@Binding ( 화면 전환 하면서 값 연결시키기)
@Binding wrapper는 두 Views 에서 값을 공유하기 위해 쓰입니다.
이는 여러 Views 에서 공유되기 위해 reference type 으로 만들어진 @ObservedObject or @EnvironmentObject와는 달라요.
먼저,
struct ContentView: View { @State var isShowing = false var body: some View { Button("button to detailView") { isShowing = true } .sheet(isPresented: $isShowing, content: { DetailView(isDetailViewShowing: $isShowing) }) } } struct DetailView: View { @Binding var isDetailViewShowing : Bool var body: some View { Button("Dismiss!") { isDetailViewShowing = false } } }
로직을 단순히 설명드리면, ContentView 에서 DetailView 를 present 할지 말지 결정하는 변수로 isShowing 을 선언했어요.
그 후 DetailView 가 present 된 상태에서 ContentView 의 isShowing 변수를 변화시키기 위해서
DetailView 에서 그 연결고리가 될 변수를 @Binding 을 이용해서 만들었어요. (isDetailViewShowing)
ContentView 에서 버튼을 누르면 isShowing 이 true 로 되고, 따라서 sheet 의 isPresented 값에 true 가 넘어가면서 DetailView 가 present 되게 됩니다. (이때, DetailView의 isDetailViewShowing 과 ContentView의 isShowing 값이 서로 연결돼요. (isDetailViewShowing property에 $isShowing 값을 넣어줌으로써 ( Binding ) ) )
DetailView가 present 된 후에, "Dismiss" 버튼을 누르면 isDetailViewShowing 값이 false 로 되면서, ContentView의 isShowing 값도 false 로 , 결국 해당 뷰 (DetailView) 가 dismiss 하게 된답니다~~
이번엔 다른 예제입니다.
좌측부터 차례대로 SimpleView, SelectionView, SimpleView 이번 예제에서는 Binding 을 두 쌍에 대해 하고있어요.
한 쌍은 화면이 나타날지 사라질지에 관한 것이고, (isShowingSheet, showingSelectionView)
한 쌍은 SimpleView 에서 나타날 이미지를 결정해요. ( isNight, isNight )
struct SimpleView: View { @State private var isNight = true @State private var isShowingSheet = false var body: some View { ZStack { VStack { Image(systemName: isNight ? "moon.stars.fill" : "cloud.sun.fill") Button { isShowingSheet = true } label: { Label("Change Time Of Day", systemImage: "clock.fill") .foregroundColor(.black) } } } .sheet(isPresented:$isShowingSheet, content: { SelectionView( isNight: $isNight, showingSelectionView: $isShowingSheet ) }) } }
struct SelectionView: View { @Binding var isNight: Bool @Binding var showingSelectionView: Bool var body: some View { VStack { Button { isNight = true showingSelectionView = false } label: { Label("Make Night", systemImage: "moon.stars.fill") .foregroundColor(.white) } Button { isNight = false showingSelectionView = false } label: { Label("Make Day", systemImage: "cloud.sun.fill") } } } }
Binding 의 첫 예제에서 화면을 나타나게 할지 말지는 설명했으므로 이번 예시에서는 isNight 변수 ( SimpleView 에서의 이미지 결정) 에 대해 알아보도록 해요.
SimpleView에서 isNight 에 따라 보이는 이미지가 달라져요
Image(systemName: isNight ? "moon.stars.fill" : "cloud.sun.fill")
SimpleView 에서 SelectionView 로 이동할 때,
isNight -> isNight
isShowingSheet -> showingSelectionView
두 쌍의 변수들이 Bind 되게 됩니다.
SelectionView 에서는 두 버튼이 있고, 첫 버튼은 isNight 을 true로, 나머지 버튼을 false 로 설정합니다.
이렇게 할 시 SimpleView 에서의 isNight 변수도 서로 Binding 되어있기 때문에 변하게 되고,
그 후 과정은 showingSelectionView 가 false 로 변하면서 해당 View (SelectionView) 가 dismiss 하게 돼요 !
(위 예제 코드에서는 핵심만 보기 쉽게 하기 위해 색상, padding, cornerRadius 등은 포함하지 않았어요. 아래 link에는 있습니다.)
완성 소스코드 github link : https://github.com/hanmok/BindingPractice
간단한 clone link: https://github.com/hanmok/BindingPractice.git
참조 링크
https://www.hackingwithswift.com/quick-start/swiftui/what-is-the-state-property-wrapper
https://www.hackingwithswift.com/quick-start/swiftui/what-is-the-binding-property-wrapper
https://www.youtube.com/watch?v=lgtB3WLEOYg
What is the @State property wrapper? - a free SwiftUI by Example tutorial
Was this page useful? Let us know! 1 2 3 4 5
www.hackingwithswift.com
What is the @Binding property wrapper? - a free SwiftUI by Example tutorial
Was this page useful? Let us know! 1 2 3 4 5
www.hackingwithswift.com
'SwiftUI > Basic Property Wrappers' 카테고리의 다른 글
PassthroughSubject VS CurrentValueSubject (0) 2021.12.10 SwiftUI ) StateObject, EnvironmentObject, ObservedObject2 (1) 2021.10.06 SwiftUI ) StateObject Apple Documentation 번역 (0) 2021.10.05 SwiftUI) State, ObservedObject, StateObject, and EnvironmentObject (0) 2021.09.13 SwiftUI) Binding, presentationMode (Two ways to dismiss view) (0) 2021.09.13