티스토리 뷰
안녕하세요. 해당 게시물은 개발하는 정대리님의 취준생을 위한 스위프트UI 앱만들기 강좌 -fundamental Tutorial(2020) 를 기반으로 했습니다.
2021.04.15 - [iOS] - [SwiftUI] 초기 설정 및 Basic 코드 짜보기
저번에 진행했던 것을 기반으로 코드를 짜기 때문에 혹시나 전 게시물을 보지 않으셨다면 보시길 추천드립니다.
이번에는 isActivated 라는 Boolean type의 변수를 사용해서 여러가지 구현을 해보려고 합니다.
일단 isActivated라는 변수를 선언해주세요.
private var isActivated: Bool = false
그리고 저번에 만들었던 ContentView.swift > HStack에서 isActivated의 상태에 따라서 padding값과 backgroundColor를 바꾸려고 합니다. 그렇다면 해당 코드에 이런 식으로 isActivated를 넣어주면 되겠죠?
.padding(isActivated ? 50 : 10)
.background(isActivated ? Color.yellow : Color.black)
.onTapGesture {
print("Hstack clicked.")
withAnimation {
self.isActivated.toggle()
}
}
self.isActivated.toggle()은 해당 변수가 true이면 false로, false이면 true로 변경해줍니다.
SwiftUI에서는 뷰가 자체적으로 다시 뷰를 그리기 때문에 toggle로 인해서 변경이 일어나면 해당 부분이 알아서 변경됩니다.
하지만 ! 우리가 원하는대로 변경이 안 될 겁니다.. !!
SwiftUI에서는 State를 값이 변화될 변수 앞에다가 사용해서 값의 변화를 감지하게 해줘야 합니다.
State를 사용하지 않으면 해당 변수가 있어도 Preview에 원하는대로 뜨지 않아요.!
// @State : 값이 변화되면 알아서 값을 렌더링, 다시 계산해준다 -> 변화된 값은 뷰에 적용됨
@State
private var isActivated: Bool = false
이렇게 하면 isActivated가 변화하는대로 뷰의 형태도 변화할겁니다.
이번에는 isActivated를 ContentView에서만 말고 다른 뷰에서도 사용해보려고 합니다.
isActivated를 다른 뷰로 데이터 이동을 시켜줘야해요, 이럴 땐 어떻게 해야할까요?
이번엔 Binding이라는 걸 사용해줄겁니다.
isActivated를 받을 뷰에다가 @Binding를 사용해서 isActivated를 선언하고, @Binding를 사용하려면 기본생성자를 설정해줘야 하기 때문에 기본생성자까지 설정해줍시다.
// 데이터를 연동시킨다
@Binding
var isActivated: Bool
// Binding를 쓸려면 기본생성자를 설정해줘야 함
init(isActivated: Binding<Bool> = .constant(false)) {
_isActivated = isActivated
}
init를 통해서 다른 뷰에서 isActivated를 받았을 때 기본적으로는 false로 설정을 해주고, 받은 isActivated(isActivated)를 현재 뷰가 가지고 있는 isActivated(_isActivated)에 넣어줍니다.
해당 뷰에서 온 isActivated가 값을 가지고 있다면 그 값을 현재 뷰의 isActivated에 넣어주게 됩니다.
Q. 왜 변수 앞에다가 _를 쓰나요?
A. _isActivated는 Binding struct 기반의 변수이기 때문입니다. @Binging 기반의 변수는 3가지의 접근방식이 있는데요,
첫번째는 self._isActivated , 두번째는 self.isActivated, 세번째는 self.$isActivated 입니다.
세가지 모두 같은 의미를 가진 것은 아니고 _와 $은 Binding<Bool>의 의미라면,
isActivated 자체를 쓰는 두번째는 self._isActivated.wrappedValue와 같은 의미로 Bool자체를 뜻합니다.
_와 $도 디테일하게 보면 Access level의 차이가 있다고 하네요..!
_ 변수에 관한 스택오버플로우 답변 :
그렇다면 이제, ContentView에서 사용하는 isActivated를 다른 뷰로 이동시켜보겠습니다.
HStack {
MyVstackView(isActivated: $isActivated)
MyVstackView(isActivated: $isActivated)
MyVstackView(isActivated: $isActivated)
}
NavigationLink(
destination: MyTextView(isActivated: $isActivated)) {
Text("네비게이션")
.fontWeight(.heavy)
.font(.system(size: 30))
.padding(10)
.background(Color.orange)
.foregroundColor(Color.white)
.cornerRadius(30)
} .padding(.top, 50)
HStack에서는 MyVstackView로, NavigationLink에서는 MyTextView로 isActivated 데이터를 이동시키는 코드입니다.
이런식으로 이동한 데이터는
MyVstackView.swift
var body: some View {
VStack {
Text("1!")
.fontWeight(.bold)
.font(.system(size: 40))
Text("2!")
.fontWeight(.bold)
.font(.system(size: 40))
Text("3!")
.fontWeight(.bold)
.font(.system(size: 40))
}
.padding(self.isActivated ? 10 : 0)
.background(self.isActivated ? Color.green : Color.red)
}
다른 뷰에서도 사용되게 됩니다.
@State와 @Binding를 사용하면 SwiftUI를 더 폭 넓게 사용할 수 있습니다.
전체 코드는 github에 올려두었습니다.
'SwiftUI' 카테고리의 다른 글
[SwiftUI] WebView 띄우기 (0) | 2021.04.27 |
---|---|
[SwiftUI] 초기 설정 및 Basic 코드 짜보기 (0) | 2021.04.15 |