[SwiftUI] Preference Key & coordinatespace

Uno·2022년 3월 27일
0

SwiftUI

목록 보기
29/30

Preference

  • key - value 로 구성된 데이터 전달 수단입니다.
  • 전달 방향은 하위뷰 -> 상위뷰 입니다.

구현방법

private struct ScrollOffsetPreferenceKey: PreferenceKey {
    static var defaultValue: CGPoint = .zero
    static func reduce(value: inout CGPoint, nextValue: () -> CGPoint) {
	  	// do something 
    }
}
- 1. “PreferenceKey” 를 따르는 구조체를 정의합니다.
- 2. reduce 메소드를 생성합니다.

reduce 메소드 우리가 선언한 “PreferenceKey” 를 사용하는 하위뷰를 순회합니다. 동시에, 상위뷰가 접근할 수 있는 값을 취합해줍니다.

하위뷰 코드입니다.

GeometryReader { geometry in
    Color.clear.preference(
		key: ScrollOffsetPreferenceKey.self,
		value: geometry.frame(in: .named("scrollView")).origin
    )
}
.frame(width: 0, height: 0)
- Color에 보면 .preference 를 통해서 값을 전달해주고 있습니다.
- key 는 “ScrollOffsetPreferenceKey.self” 입니다.
- value 는 “geometry.frame(in: .named(“scrollView”)).origin” 입니다.

하위뷰 전체 코드를 보면서 설명하겠습니다.

struct TrackableScrollView<Content: View>: View {
    let axes: Axis.Set
    let offsetChanged: (CGPoint) -> Void
    let content: Content
    
    init(axes: Axis.Set = .vertical,
         offsetChanged: @escaping (CGPoint) -> Void = { _ in },
         @ViewBuilder content: () -> Content) {
        self.axes = axes
        self.offsetChanged = offsetChanged
        self.content = content()
    }
    
    var body: some View {
        SwiftUI.ScrollView(axes, showsIndicators: false) {
            GeometryReader { geometry in
                Color.clear.preference(
				    key: ScrollOffsetPreferenceKey.self,
                 value: geometry.frame(in: .named("scrollView")).origin
                )
            }
            .frame(width: 0, height: 0)
            content
        }
        .coordinateSpace(name: "scrollView")
        .onPreferenceChange(ScrollOffsetPreferenceKey.self,
								perform: offsetChanged
		   )
    }
}

private struct ScrollOffsetPreferenceKey: PreferenceKey {
    static var defaultValue: CGPoint = .zero
    static func reduce(value: inout CGPoint, nextValue: () -> CGPoint) {
    }
}
  • 현재 value에 있는 .named(“scrollView”) 와 .coordinateSpace(name: “scrollView”) 가 연결되어 있는 상태입니다.
  • 위치정보의 이름을 “scrollView” 로 정의하고, 해당 값을 Preference로 전달하고 있습니다.
  • cooridnateSpace 수식어 아래보면 “.onPreferenceChange” 를 통해서 해당 값이 변경될 때, “offsetChanged” 가 호출되도록 구성하고 있습니다.
  • 정리하면, geometry.frame(in:).origin 의 값이 변경되면, offsetChanged 가 호출됩니다. 그리고 그것을 상위뷰에서 이제 사용할 수 있습니다.

참고자료

profile
iOS & Flutter

0개의 댓글