【问题标题】:Get CGRect of View获取视图的CGRect
【发布时间】:2020-05-29 13:29:55
【问题描述】:

我正在使用“RectGetter”来获取CGRectView

像这样:

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)

有没有更可靠的方法(不崩溃)来获得ViewCGRect

【问题讨论】:

  • 问题是没有得到 CGRect;这就是你用它做什么。您正在伸出手并将其设置在其他地方。这通常不是您想要在 SwiftUI 中进行布局的方式(这里的典型工具是 Preference、Anchor 或 Alignment,而不是 .async setter)。这些视图不是类;它们是结构。没有保证 self 会在调用 main.async 时以有意义的方式存在。目前尚不清楚在这种情况下self.$rect 是什么以及接下来会发生什么。你想达到什么样的布局?
  • 我在许多博客中都看到了它,但我没有从 Apple 看到它,而且我认为它不是基于任何承诺有效的东西。它恰好起作用(Asperi 的回答很好,因为它在几何存在时评估它,但它仍然依赖于我从未见过 Apple 建议承诺的行为。)SwiftUI-Lab 有一个非常好的系列关于如何在 SwiftUI 中进行声明式布局。 swiftui-lab.com/alignment-guidesswiftui-lab.com/communicating-with-the-view-tree-part-1
  • 也特别提到这一点:swiftui-lab.com/state-changes 我通常发现如果目标是布局,那么对齐指南是您真正想要的工具,而不是“布局它,让状态变量图事情出来,然后重新布置”,我怀疑这就是你在这里所做的(在我重写所有内容以使用 AlignmentGuides 之前,我已经自己完成了)。
  • (需要明确的是,我不确定这些异步设置器是否无效。显然我们可以进行异步工作并让该工作集状态变量,这是完全支持的。但是布局导致设置器重新布局似乎违反了 SwiftUI 的声明性性质,目前尚不清楚这是否是一种可能会破坏的 hack、一种恰好依赖于坚实基础的不良做法,或者实际上很好。SwiftUI-Lab 一直是我最可靠的资源管理器不过,我发现了这些问题。
  • 感谢 Rob 精心制作的 cmets,确实,Apple 对此没有任何官方消息(与 SwiftUI 上的大部分文档一样)。 AlignmentGuides 可能是正确的方法,但现在我有点懒于学习该 API,所以我将尝试 Asperis 的建议。

标签: crash swiftui cgrect


【解决方案1】:

我使用这样的功能。从 Xcode 11.1 开始工作

func rectReader(_ binding: Binding<CGRect>) -> some View {
    return GeometryReader { (geometry) -> AnyView in
        let rect = geometry.frame(in: .global)
        DispatchQueue.main.async {
            binding.wrappedValue = rect
        }
        return AnyView(Rectangle().fill(Color.clear))
    }
}

同理

Text("Test").background(rectReader($rect))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-12
    • 1970-01-01
    相关资源
    最近更新 更多