You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在SwiftUI中通过纯SwiftUI方式实现自定义GeometryReader

实现方案

你可以通过SwiftUI原生的PreferenceKey机制实现纯SwiftUI的尺寸读取,无需依赖UIKit桥接,完整实现如下:

首先定义内部用的尺寸存储PreferenceKey:

private struct SizePreferenceKey: PreferenceKey {
    static var defaultValue: CGSize = .zero
    static func reduce(value: inout CGSize, nextValue: () -> CGSize) {
        value = nextValue()
    }
}

然后修改你的CustomGeometryReaderView实现:

struct CustomGeometryReaderView<Content: View>: View {
    @ViewBuilder let content: (CGSize) -> Content
    // 存储读取到的可用尺寸
    @State private var availableSize: CGSize = .zero
    
    var body: some View {
        // 撑满父视图提供的所有可用空间
        Color.clear
            .background(
                // 背景层用GeometryReader读取当前视图的真实尺寸
                GeometryReader { proxy in
                    Color.clear
                        .preference(key: SizePreferenceKey.self, value: proxy.size)
                }
            )
            // 监听尺寸变化,更新State
            .onPreferenceChange(SizePreferenceKey.self) { newSize in
                availableSize = newSize
            }
            // 把真实尺寸传入content闭包渲染,对齐方式和系统GeometryReader保持一致
            .overlay(content(availableSize), alignment: .topLeading)
    }
}

使用方式和你原有代码完全兼容:

struct ContentView: View {
    var body: some View {
        CustomGeometryReaderView { proxy in
            Color.red
                .onAppear() {
                    print(proxy)
                }
        }
    }
}

说明

  • 整个实现完全基于原生SwiftUI API,没有用到任何UIKit相关的桥接逻辑
  • 布局行为和系统GeometryReader完全一致:自定义视图会先占满父视图提供的所有可用空间,再把读取到的尺寸传给内部内容,内容默认从左上角开始布局
  • 如果需要扩展支持坐标空间查询、frame读取等能力,只需要把传给content的参数从CGSize替换为自定义的Proxy结构体,在PreferenceKey读取阶段采集对应参数即可

内容的提问来源于stack exchange,提问作者swiftPunk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 17:45:01