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

SwiftUI中如何在PreviewProvider内用GeometryProxy更新LayoutData类属性?

解决方案

方法1:利用预览容器的真实GeometryProxy(推荐)

在预览中用GeometryReader包裹子视图,直接将预览画布提供的GeometryProxy传入LayoutData,预览会自动适配当前画布尺寸,效果更贴近真实场景:

struct ChildView_Previews: PreviewProvider {
    static var previews: some View {
        GeometryReader { geo in
            ChildView(layoutData: LayoutData(geo: geo))
        }
    }
}

方法2:手动模拟GeometryProxy实例

如果需要固定预览尺寸,可直接创建模拟的GeometryProxy(需确认当前Swift版本支持该初始化方法),模拟常见设备的屏幕参数:

struct ChildView_Previews: PreviewProvider {
    static var previews: some View {
        // 模拟iPhone 14的屏幕尺寸与安全区域
        let fakeGeo = GeometryProxy(
            containerSize: CGSize(width: 390, height: 844),
            safeAreaInsets: EdgeInsets(top: 47, leading: 0, bottom: 34, trailing: 0)
        )
        ChildView(layoutData: LayoutData(geo: fakeGeo))
    }
}

优化LayoutData(可选)

既然你只需要屏幕宽度,可以在LayoutData中封装宽度逻辑,避免直接暴露GeometryProxy,同时简化预览适配:

class LayoutData {
    private let screenWidth: CGFloat
    
    // 正常业务逻辑初始化
    init(geo: GeometryProxy) {
        self.screenWidth = geo.size.width
    }
    
    // 预览专用初始化
    init(previewScreenWidth: CGFloat) {
        self.screenWidth = previewScreenWidth
    }
    
    // 对外提供宽度属性
    var width: CGFloat { screenWidth }
}

预览时直接传入目标宽度即可,无需处理GeometryProxy:

struct ChildView_Previews: PreviewProvider {
    static var previews: some View {
        ChildView(layoutData: LayoutData(previewScreenWidth: 390))
    }
}

以上方案均满足你的需求:无需使用UIScreen.main.width、不给子视图添加额外属性、不需要额外变量,即可让子视图在预览中正常渲染。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 18:31:03