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
相关产品推荐
相关产品推荐

