일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- url 관찰
- oberve url
- Side Menu
- transformation.map
- ViewBuilder
- 스크롤 탭
- Android
- base64 변환
- development language
- 상단 탭바
- DevelopmentRegion
- pod install
- SwiftUI
- ios
- Tuist
- scrolling tab
- DataBinding
- 개발자 면접
- GeometryReader
- 기존 앱
- List
- swift #swift keychain #keychain 사용법
- url 추적
- detect url
- notifychanged
- Swift Package Manager
- convert base64
- UIPresentationController
- swift
- UIViewControllerTransitioningDelegate
- Today
- Total
버그 잡이
SwiftUI - @State, @Binding 개념 이해하기 본문
@State
SwiftUI에 의해 관리되는 값을 읽고 쓰는 Property Wrapper 타입
"Property Wrapper "
- 프로퍼티를 감싸 특별한 타입으로 만들어주는 친구.
- 감싸는 행위를 통해서 코드 추가 없이 프로퍼티에 특정 기능을 추가할 수 있다.
"SwiftUI에 의해 관리된다"
- 변수에 변화가 생겼을때 해당 value의 appearance를 무효화 하고 다시 body 값을 계산
즉, 변수에 변화가 생겼을때, 이를 화면에 바로 반영할 수 있게 도와주는 Property Wrapper가 @State입니다.
@State 사용법
아래는 공식 문서에 있는 예제입니다.
isPlaying값에 따라 Button의 title이 달라지는 것을 볼 수 있습니다.
struct PlayButton: View {
@State private var isPlaying: Bool = false // Create the state.
var body: some View {
Button(isPlaying ? "Pause" : "Play") { // Read the state.
isPlaying.toggle() // Write the state.
}
}
}
State를 사용할떄 주의할 부분이 있는데요.
"Private으로 선언하고 가장 상위 뷰에서 @State를 관리하게 하라는 것입니다."
@State가 하위뷰에서 초기화 되면 SwiftUI storage 공간에서 conflict가 날 수 있다고 합니다.
그래서 하위 뷰에 공유하려면 read-only로 공유하거나 binding으로 공유하라고 합니다.
@Binding
Source of truth에 의해 소유되는 값을 읽고 쓰는 Property Wrapper 타입
"Source of truth에 의해 소유되는"
- 말이 좀 어려운데요...
- 여기서 말하는 Source of truth는 @State로 선언된 프로퍼티를 말합니다.
- 위에서 말했듯이 @Binding은 @State값을 하위 뷰에 공유하기 위해서 사용됩니다.
- 즉, @Binding은 @State에 의해서 소유되는 하나의 "연결용" property wrapper 입니다.
정리하자면
1. @Binding으로 감싸진 값은 @State에 의해서 소유되는 값이다
2. @Binding은 @State값을 하위뷰에서 read, write 할 수 있게 도와준다.
@Binding 사용법
struct PlayButton: View {
@Binding var isPlaying: Bool
var body: some View {
Button(isPlaying ? "Pause" : "Play") {
isPlaying.toggle()
}
}
}
struct PlayerView: View {
var episode: Episode
@State private var isPlaying: Bool = false
var body: some View {
VStack {
Text(episode.title)
.foregroundStyle(isPlaying ? .primary : .secondary)
PlayButton(isPlaying: $isPlaying) // Pass a binding.
}
}
}
PlayButton에 isPlaying값을 넘겨줄때 '$'을 앞에 붙여줍니다.
$를 붙여준다는 것은 @State로 선언된 값의 projectedValue를 넘겨준다는 것을 의미합니다.
@State의 내부 코드를 보면 projectedValue가 Binding<Value>로 선언되어 있는 것으로 볼 수 있습니다.
하위뷰에 value를 직접 전달하는 것이 아니라 Binding을 전달해서 위에서 말한 conflict 이슈를 해결합니다.
@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
@frozen @propertyWrapper public struct State<Value> : DynamicProperty {
public init(wrappedValue value: Value)
public init(initialValue value: Value)
public var wrappedValue: Value { get nonmutating set }
public var projectedValue: Binding<Value> { get }
}
*참고
https://developer.apple.com/documentation/swiftui/state
https://developer.apple.com/documentation/swiftui/binding
'SwiftUI' 카테고리의 다른 글
SwiftUI 성능 이해 및 최적화 방법 알아보기 (1) | 2024.06.07 |
---|---|
SwiftUI List 기본 스타일 지우기 (0) | 2024.03.01 |
SwiftUI - List에서 원하는 Row로 스크롤 하기 #scrollTo (0) | 2023.07.29 |
SwiftUI - scrollIndicators() 로 textEditor 스크롤바 hidden 처리하기 (0) | 2023.06.18 |
SwiftUI - Paging 되는 상단 tabbar 구현하기 (0) | 2023.05.20 |