오늘의 내용은?
앞에서 Property Wrapper에 관하여 포스팅을 하였습니다. Property Wrapper는 프로퍼티에 미리 정의해둔 연산을 통해서 값을 관리할 수 있도록 도와줍니다. 오늘은 Property Wrapper가 개발에서 실제로 어떻게 쓰이는지 확인해보도록 하겠습니다.
@State
SwiftUI에서 상태변경를 위에서 자주 쓰이는 property wrapper중 하나인데 공식문서에서는 아래와 같이 정의가 되어있습니다.
- SwiftUI에서 값을 관리하고 읽고 쓸 수 있는 property wrapper입니다.
- @State 속성은 속성 선언에 상태를 추가하고 초기값을 설정할 때 사용됩니다.
- @State로 선언된 속성을 private로 선언하면 memberwise initializer(구조체가 가지는 모든 속성을 초기화하는 기본 생성자)에서 이 속성을 설정하는 것을 방지할 수 있습니다.
- 상태는 뷰 계층에서 가장 높은 뷰에 private으로 선언하여 상태에 접근해야 하는 뷰에만 접근을 허용하는 것이 좋습니다.
- 하위 뷰에서도 접근이 필요할 경우 바인딩을 사용하여 안전하게 접근할 수 있습니다.
- 상태 속성은 어떤 스레드에서도 안전하게 변경될 수 있습니다.
🤔내용을 보면 뷰 값을 관리한다, private로 선언하는 것이 좋다, 하위 뷰에서도 접근이 가능하다. 라고 되어있고 살을 덧붙여서 정리를 해보았습니다.
@State는 뷰에서 상태의 값을 관리하며 뷰의 상태 변화를 감지하고 변경될 때 마다 해당 뷰를 다시 그리도록 합니다. 특히나 하위 뷰에서 접근이 가능합니다.
@State 예시
숫자 증가 및 감소 버튼을 구현하여 실시간으로 UI에 숫자가 변경되는 것으로 예시를 들어보겠습니다.
- @State를 사용하여 초기 숫자 변수 number를 정의하였습니다. @State는 SwiftUI에서 상태를 관리하는 속성으로, 값이 변경될 때 뷰가 다시 렌더링됩니다.
- “숫자 감소” 버튼을 클릭하면 number 값이 1씩 감소하도록 정의되었고, “숫자 증가” 버튼은 그 반대로 1씩 증가하는 동작을 하도록 설정하였습니다.
영상을 통해 각 버튼을 클릭할 때마다 number 값이 즉시 변경되고, 이 변경 사항이 UI에 반영되어 뷰가 실시간으로 업데이트되는 것을 확인할 수 있습니다. @State 덕분에 버튼 액션에 따라 UI가 자동으로 다시 그려지게 됩니다.
import SwiftUI
struct StateEx: View {
@State private var number: Int64 = 0
var body: some View {
VStack(spacing: 20) {
Text("\\(number)")
.font(.largeTitle)
HStack(spacing: 30) {
Button(action: {
number -= 1
}, label: {
Text("숫자 감소")
})
Button(action: {
number += 1
}, label: {
Text("숫자 증가")
})
}
}
}
}
#Preview {
StateEx()
}
@Binding
State로 정의한 값을 하나의 뷰에서만 사용하기에는 아쉽잖아요? 하위 뷰에서는 Binding이라는 property wrapper를 통해 값을 사용할 수 있습니다.
- 데이터를 소유한 원본 값에 대해 읽고 쓸 수 있는 property wrapper 유형입니다.
- 바인딩을 사용하여 데이터를 저장하는 속성과 데이터를 표시하고 변경하는 뷰 간에 양방향 연결을 생성할 수 있습니다.
- 바인딩은 데이터를 직접 저장하는 대신 다른 곳에 저장된 “source of truth“로부터 속성을 연결합니다.
@Binding은 데이터의 원천을 참조하며 직접 값을 수정하고 사용 가능하게 만들어 줍니다.
@Binding 예시
두개의 뷰에서 @Binding을 활용하여 하나의 값을 참조하여 숫자 값을 수정하는 예시입니다.
- 상위 뷰에서 number 변수를 @State로 정의하여 상태를 관리하고, 이를 하위 뷰에서 참조할 수 있도록 하였습니다.
- sheet가 활성화될지를 제어하기 위해 subviewToggle이라는 @State 변수를 사용하여 뷰의 표시 여부를 관리합니다.
- “숫자 수정하기” 버튼을 클릭하면 subviewToggle의 값이 반전(false에서 true 또는 그 반대)되며, 이 값에 따라 sheet가 나타나거나 사라지게 됩니다.
- sheet는 isPresented라는 감시자에 subviewToggle의 값이 true로 반환될 때 sheet를 나타나게 해줍니다.
- 이때 sheet를 통해 보여지는 하위 뷰에서는 상위 뷰의 값을 사용하기 위해 @Binding을 정의하였으며, 이를 $number와 함께 연결하여 넘겨줍니다.
BindingExSubView는 @Binding을 통해 상위 뷰의 number 값과 연결되어 있으므로, 하위 뷰에서 숫자를 변경하면 그 변경 사항이 상위 뷰에도 적용됩니다. 이를 통해 두 뷰 간의 값이 실시간으로 동기화됩니다. 영상으로 이제 결과를 확인해 보세요!
import SwiftUI
struct BindingEx: View {
@State var number: Int64 = 0
@State var subviewToggle: Bool = false
var body: some View {
Text("\\(number)")
.font(.largeTitle)
Button(action: {
subviewToggle.toggle()
}, label: {
Text("숫자 수정하기")
})
.sheet(isPresented: $subviewToggle, content: {
BindingExSubView(number: $number)
})
.padding()
}
}
struct BindingExSubView: View {
@Binding var number: Int64
var body: some View {
VStack(spacing: 20) {
Text("\\(number)")
.font(.largeTitle)
HStack(spacing: 30) {
Button(action: {
number -= 1
}, label: {
Text("숫자 감소")
})
Button(action: {
number += 1
}, label: {
Text("숫자 증가")
})
}
}
}
}
#Preview {
BindingEx()
}
State와 Binding을 통해서 뷰 간에 데이터를 손 쉽게 사용할 수 있고 관리할 수 있게 됩니다.
이렇게 오늘은 뷰 상태변경을 정리해보았습니다. 다음 내용은 뷰 상태변경 제2장의 내용을 정리 해볼려고 합니다! 부족한 내용이지만 끝까지 읽어봐주셔서 감사합니다. 지인에게 추천받은 개발자 속담으로 마무리하도록 하겠습니다! 파이팅입니다~
“안되는 것은 없다. 다만 시간이 조금 필요하거나 조금 더 필요할 뿐”
'iOS 개발 > SwiftUI' 카테고리의 다른 글
[SwiftUI] @Published 썼는데도 View가 안 바뀐다? (0) | 2025.05.30 |
---|---|
[SwiftUI] Splash & Onboarding 화면 구현 리뷰 (Feat. 나만의 Todo) (1) | 2025.05.26 |
[SwiftUI] Figma 비율 그대로! 개발하는 Constants 구조체 만들기 (1) | 2025.05.24 |
뷰 상태변경 제 2장 (8) | 2024.11.13 |
Property Wrapper (2) | 2024.09.22 |