티스토리 뷰

SwiftUI

[SwiftUI] State와 Binding

XXIN-dev 2021. 4. 15. 16:02

안녕하세요. 해당 게시물은 개발하는 정대리님의 취준생을 위한 스위프트UI 앱만들기 강좌 -fundamental Tutorial(2020) 를 기반으로 했습니다.

 

2021.04.15 - [iOS] - [SwiftUI] 초기 설정 및 Basic 코드 짜보기

 

[SwiftUI] 초기 설정 및 Basic 코드 짜보기

안녕하세요. 해당 게시물은 개발하는 정대리님의 취준생을 위한 스위프트UI 앱만들기 강좌 -fundamental Tutorial(2020) 를 기반으로 했습니다. SwiftUI를 사용하기 위해선 먼저 새 프로젝트를 열 때 New pr

cannabuffer.tistory.com

저번에 진행했던 것을 기반으로 코드를 짜기 때문에 혹시나 전 게시물을 보지 않으셨다면 보시길 추천드립니다.

 


 

이번에는 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의 차이가 있다고 하네요..!

 

_ 변수에 관한 스택오버플로우 답변 :

stackoverflow.com/questions/65209314/what-does-the-underscore-mean-before-a-variable-in-swiftui-in-an-init


그렇다면 이제, 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
링크
최근에 올라온 글
최근에 달린 댓글