iOS 기본 (SwiftUI)
[iOS - SwiftUI] Preference, PreferenceKey, preference(key:value:), onPreferenceChange() 사용 방법 (하위뷰에서 상위뷰로 데이터 넘기는 방법)
jake-kim
2022. 11. 3. 22:01
Preference 란?
- key와 vallue로 구성된 데이터 전달 메소드
- 데이터 전달: 하위 뷰 -> 상위 뷰
Preference 사용 방법
- 키를 가지고 접근
- 1. 키 등록: preferenceKey 프로토콜 준수
- 2. 하위뷰에서 값 송신: preference(key:value:) 메소드
- 3. 상위뷰에서 값 수신: onPreferenceChange() 메소드
ex) 하위 뷰의 navigationTitle이 변경될때마다 부모 뷰에서 타이틀이 변경될때마다 print하기
- 1. 키 등록: preferenceKey 프로토콜 준수
// PreferenceKey 내부 코드
@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
public protocol PreferenceKey {
associatedtype Value
static var defaultValue: Self.Value { get }
static func reduce(value: inout Self.Value, nextValue: () -> Self.Value)
}
- preferenceKey 준수하는 NavigationBarTitleKey 정의
struct NavigationBarTitleKey: PreferenceKey {
static var defaultValue: String = ""
static func reduce(value: inout String, nextValue: () -> String) {
value = nextValue()
}
}
- 상위뷰와 하위뷰 준비
- 상위뷰는 NavigationView
- 하위뷰는 NavigationView의 Link부분에 들어가는 뷰
// 상위뷰
struct ContentView: View {
var messages: [String] {
(0...100).map(String.init)
}
var body: some View {
NavigationView {
List(messages, id: \.self) { message in
NavigationLink {
SomeView(title: message)
} label: {
Text(message)
}
}
.navigationBarTitle("Messages")
}
}
}
// 하위뷰
struct SomeView: View {
let title: String
var body: some View {
Text(title)
.navigationBarTitle(title)
.preference(key: NavigationBarTitleKey.self, value: title)
}
}
- 2. 하위뷰에서 값 송신: preference(key:value:) 메소드
struct SomeView: View {
let title: String
var body: some View {
Text(title)
.navigationBarTitle(title)
.preference(key: NavigationBarTitleKey.self, value: title) // <-
}
}
- 3. 상위뷰에서 값 수신: onPreferenceChange() 메소드
struct ContentView: View {
var messages: [String] {
(0...100).map(String.init)
}
var body: some View {
NavigationView {
List(messages, id: \.self) { message in
NavigationLink {
SomeView(title: message)
} label: {
Text(message)
}
}
.navigationBarTitle("Messages")
}
.onPreferenceChange(NavigationBarTitleKey.self) { title in // <-
print(title)
}
}
}
완성) 스크롤 할때마다 값 navigationTitle의 값을 print
* 전체 코드: https://github.com/JK0369/ExPreferenceKey
* 참고
https://developer.apple.com/documentation/swiftui/preferencekey
https://developer.apple.com/documentation/swiftui/grid/preference(key:value:)