获取 CGRect 视图
Get CGRect of View
我正在使用 "RectGetter" 获取 View
的 CGRect
。
像这样:
Text("Hello")
.background(RectGetter(rect: self.$rect))
struct RectGetter: View {
@Binding var rect: CGRect
var body: some View {
GeometryReader { proxy in
self.createView(proxy: proxy)
}
}
func createView(proxy: GeometryProxy) -> some View {
DispatchQueue.main.async {
self.rect = proxy.frame(in: .global) // crash here
}
return Rectangle().fill(Color.clear)
}
}
但有时我在设置矩形时会崩溃。
Thread 0 name:
Thread 0 Crashed:
0 libsystem_kernel.dylib 0x00000001a1ec5ec4 __pthread_kill + 8
1 libsystem_pthread.dylib 0x00000001a1de5724 pthread_kill$VARIANT$armv81 + 216 (pthread.c:1458)
2 libsystem_c.dylib 0x00000001a1d358c0 __abort + 112 (abort.c:147)
3 libsystem_c.dylib 0x00000001a1d35850 abort + 112 (abort.c:118)
4 AttributeGraph 0x00000001cce56548 0x1cce25000 + 202056
5 AttributeGraph 0x00000001cce2b980 0x1cce25000 + 27008
6 SwiftUI 0x00000001d89ce9b4 $s7SwiftUI27_PositionAwareLayoutContextV10dimensionsSo6CGSizeVvg + 56 (<compiler-generated>:0)
7 SwiftUI 0x00000001d8a43584 $sSo6CGSizeVIgd_ABIegr_TRTA + 24 (<compiler-generated>:0)
8 SwiftUI 0x00000001d8a43a54 $s7SwiftUI13GeometryProxyV4sync33_4C4BAC551E328ACCA9CD3748EDC0CC3ALLyxSgxyXElFxAA9ViewGraphCXEfU_... + 92 (GeometryReader.swift:126)
9 SwiftUI 0x00000001d8a43f20 $s7SwiftUI13GeometryProxyV4sync33_4C4BAC551E328ACCA9CD3748EDC0CC3ALLyxSgxyXElFxAA9ViewGraphCXEfU_... + 20 (<compiler-generated>:0)
10 SwiftUI 0x00000001d8c4842c $s7SwiftUI16ViewRendererHostPAAE06updateC5Graph4bodyqd__qd__AA0cG0CXE_tlF + 80 (ViewRendererHost.swift:64)
11 SwiftUI 0x00000001d8a438d4 $s7SwiftUI13GeometryProxyV5frame2inSo6CGRectVAA15CoordinateSpaceO_tF + 196 (GeometryReader.swift:125)
12 MyApp 0x0000000102cf5c54 closure #1 in RectGetter.createView(proxy:) + 128 (RectGetter.swift:22)
是否有更可靠的方法(不会崩溃)来获取 View
的 CGRect
?
更新:改进并简化了一个可能的解决方案,以通过辅助扩展读取任何坐标 space 中任何视图的矩形。从 Xcode 11.1 开始工作,用 Xcode 13.3 重新测试。
主要部分:
func rectReader(_ binding: Binding<CGRect>, _ space: CoordinateSpace = .global) -> some View {
GeometryReader { (geometry) -> Color in
let rect = geometry.frame(in: space)
DispatchQueue.main.async {
binding.wrappedValue = rect
}
return .clear
}
}
用法相同
Text("Test").background(rectReader($rect))
或使用新扩展名
Text("Test").reading(rect: $rect)
另一种方法是使用首选项键,as outlined here。
综上所述,可以设置修饰符:
struct SizePreferenceKey: PreferenceKey {
static var defaultValue: CGRect = .zero
static func reduce(value: inout CGRect, nextValue: () -> CGRect) {
value = nextValue()
}
}
struct SizeModifier: ViewModifier {
private var sizeView: some View {
GeometryReader { geometry in
Color.clear.preference(key: SizePreferenceKey.self, value: geometry.frame(in: .global))
}
}
func body(content: Content) -> some View {
content.background(sizeView)
}
}
然后使用那个:
SomeView()
.modifier(SizeModifier())
.onPreferenceChange(SizePreferenceKey.self) { print("My rect is: \([=11=])") }
我正在使用 "RectGetter" 获取 View
的 CGRect
。
像这样:
Text("Hello")
.background(RectGetter(rect: self.$rect))
struct RectGetter: View {
@Binding var rect: CGRect
var body: some View {
GeometryReader { proxy in
self.createView(proxy: proxy)
}
}
func createView(proxy: GeometryProxy) -> some View {
DispatchQueue.main.async {
self.rect = proxy.frame(in: .global) // crash here
}
return Rectangle().fill(Color.clear)
}
}
但有时我在设置矩形时会崩溃。
Thread 0 name:
Thread 0 Crashed:
0 libsystem_kernel.dylib 0x00000001a1ec5ec4 __pthread_kill + 8
1 libsystem_pthread.dylib 0x00000001a1de5724 pthread_kill$VARIANT$armv81 + 216 (pthread.c:1458)
2 libsystem_c.dylib 0x00000001a1d358c0 __abort + 112 (abort.c:147)
3 libsystem_c.dylib 0x00000001a1d35850 abort + 112 (abort.c:118)
4 AttributeGraph 0x00000001cce56548 0x1cce25000 + 202056
5 AttributeGraph 0x00000001cce2b980 0x1cce25000 + 27008
6 SwiftUI 0x00000001d89ce9b4 $s7SwiftUI27_PositionAwareLayoutContextV10dimensionsSo6CGSizeVvg + 56 (<compiler-generated>:0)
7 SwiftUI 0x00000001d8a43584 $sSo6CGSizeVIgd_ABIegr_TRTA + 24 (<compiler-generated>:0)
8 SwiftUI 0x00000001d8a43a54 $s7SwiftUI13GeometryProxyV4sync33_4C4BAC551E328ACCA9CD3748EDC0CC3ALLyxSgxyXElFxAA9ViewGraphCXEfU_... + 92 (GeometryReader.swift:126)
9 SwiftUI 0x00000001d8a43f20 $s7SwiftUI13GeometryProxyV4sync33_4C4BAC551E328ACCA9CD3748EDC0CC3ALLyxSgxyXElFxAA9ViewGraphCXEfU_... + 20 (<compiler-generated>:0)
10 SwiftUI 0x00000001d8c4842c $s7SwiftUI16ViewRendererHostPAAE06updateC5Graph4bodyqd__qd__AA0cG0CXE_tlF + 80 (ViewRendererHost.swift:64)
11 SwiftUI 0x00000001d8a438d4 $s7SwiftUI13GeometryProxyV5frame2inSo6CGRectVAA15CoordinateSpaceO_tF + 196 (GeometryReader.swift:125)
12 MyApp 0x0000000102cf5c54 closure #1 in RectGetter.createView(proxy:) + 128 (RectGetter.swift:22)
是否有更可靠的方法(不会崩溃)来获取 View
的 CGRect
?
更新:改进并简化了一个可能的解决方案,以通过辅助扩展读取任何坐标 space 中任何视图的矩形。从 Xcode 11.1 开始工作,用 Xcode 13.3 重新测试。
主要部分:
func rectReader(_ binding: Binding<CGRect>, _ space: CoordinateSpace = .global) -> some View {
GeometryReader { (geometry) -> Color in
let rect = geometry.frame(in: space)
DispatchQueue.main.async {
binding.wrappedValue = rect
}
return .clear
}
}
用法相同
Text("Test").background(rectReader($rect))
或使用新扩展名
Text("Test").reading(rect: $rect)
另一种方法是使用首选项键,as outlined here。
综上所述,可以设置修饰符:
struct SizePreferenceKey: PreferenceKey {
static var defaultValue: CGRect = .zero
static func reduce(value: inout CGRect, nextValue: () -> CGRect) {
value = nextValue()
}
}
struct SizeModifier: ViewModifier {
private var sizeView: some View {
GeometryReader { geometry in
Color.clear.preference(key: SizePreferenceKey.self, value: geometry.frame(in: .global))
}
}
func body(content: Content) -> some View {
content.background(sizeView)
}
}
然后使用那个:
SomeView()
.modifier(SizeModifier())
.onPreferenceChange(SizePreferenceKey.self) { print("My rect is: \([=11=])") }