.reportWidth() ...
ไธป่ฆๅ่ฝ
view.reportWidth(to: key) ๅๅ ฑ่ชๅทฑ็ๅฏฌๅบฆ (geometry.size.width) ็ตฆ
key
(PreferenceKey)ใview.reportFrame(to: key, in: space) ๅๅ ฑ่ชๅทฑ็ geometry.frame(in: space) ็ตฆ
key
ใ
import SwiftUI
// ๐View + pref (generic methods)
extension View {
// โญ๏ธ ๅๅ ฑ GeometryProxy ็ๅฑฌๆง็ตฆ `key`
// - view.report(to: key) { $0.size }
public func report<K: PreferenceKey>(
// ่ฆๅๅ ฑ็ๅฐ่ฑก (PreferenceKey)
to key: K.Type = K.self,
// ่ฆๅๅ ฑ GeometryProxy ็ๅชๅๅฑฌๆง๏ผ
// โ ๏ธ ๆณจๆ๏ผ
// ้่ฃก็ `value` closure ๅฟ
้ ๆจ่จป็บ `@escaping`๏ผ
// ๅ ็บๅฎ็จๅจ GeometryReader ็ @ViewBuilder closure ่ฃก้ข๏ผ
// ่้ๅ closure ๆฌ่บซๅฐฑๆฏ `@escaping`๏ผๆไปฅๅฆๆๆฒๆๆจ่จป็่ฉฑ๏ผ
// ๆ็ข็ "escaping closure captures non-escaping parameter" ็้ฏ่ชค โผ๏ธ
value : @escaping (GeometryProxy) -> K.Value
) -> some View {
self
// โญ๏ธ 1. read self's geometry
.background(GeometryReader { geo in
Color.clear
// โญ๏ธ 2. set preference:
// report geo's attribute to `key`
.preference(key: key, value: value(geo))
})
}
// view.register(to: key) { $0.frame(in: space) }
// T๏ผๆถ้็ๅๅฅ่ณๆๅๅฅ
// K๏ผPreferenceKey, K.Value == [T]
public func register<T, K: PreferenceKey>(
to key: K.Type = K.self,
value : @escaping (GeometryProxy) -> K.Value.Element
) -> some View
where K.Value == Array<T> // โญ๏ธ ๆถ้ๅฐ K.Value == [T]
{
self
// โญ๏ธ 1. read self's geometry
.background(GeometryReader { geo in
Color.clear
// โญ๏ธ 2. set preference:
// (register geo's value to `key`)
.preference(key: key, value: [value(geo)])
})
}
}
// specialized methods
extension View {
// report width
// view.reportWidth(to: key)
public func reportWidth<K: PreferenceKey>(
to key: K.Type = K.self
) -> some View
where K.Value == CGFloat?
{
self.report(to: key) { $0.size.width }
}
// report frame
// view.reportFrame(to: key, in: space)
public func reportFrame<K: PreferenceKey>(
to key: K.Type = K.self,
in space: CoordinateSpace = .global
) -> some View
where K.Value == CGRect?
{
self.report(to: key) { $0.frame(in: space) }
}
// register frame
// view.registerFrame(to: key, in space)
public func registerFrame<K: PreferenceKey>(
to key: K.Type = K.self,
in space: CoordinateSpace = .global
) -> some View
where K.Value == [CGRect]
{
self.register(to: key) { $0.frame(in: space) }
}
}
import SwiftUI
// ๐View + anchor preference (generic methods)
extension View {
// view.register(to: FrameAnchors.self)
public func register<K: PreferenceKey>(to key: K.Type = K.self) -> some View
where K.Value == [Anchor<CGRect>]
{
self.anchorPreference(key: K.self, value: .bounds) { [$0] }
}
// view.overlay(with: FrameAnchors.self) { anchors in ... }
public func overlay<K: PreferenceKey, T: View>(
with key: K.Type = K.self,
transform: @escaping (K.Value) -> T
) -> some View
where K.Value == [Anchor<CGRect>]
{
overlayPreferenceValue(key) { transform($0) }
}
}
Last updated