UIScreen.main已弃用,SwiftUI中如何提前获取屏幕宽度?
解决方案
方法一:GeometryReader(SwiftUI原生推荐方案)
你之前对GeometryReader的顾虑是误解了它的工作逻辑——它是在布局阶段实时获取父容器的尺寸,完全适配你的需求,也是最符合SwiftUI布局体系的方案。把ZStack嵌套在GeometryReader里,用它提供的尺寸限制图片的最大宽度,这样ZStack会被约束在屏幕范围内,按钮自然固定在屏幕角落,图片则能保持原尺寸超出显示:
GeometryReader { proxy in ZStack { AsyncImage(url: URL(string: url)) { image in image } placeholder: { EmptyView() } .frame(maxWidth: proxy.size.width) buttons } }
方法二:替代UIScreen.main的API方案
如果确实不想用GeometryReader,可以通过当前窗口场景获取屏幕尺寸,替代已弃用的UIScreen.main。直接在视图里定义计算属性即可:
private var currentScreenWidth: CGFloat { guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene else { return 375 // 给默认值适配多数设备 } return windowScene.screen.bounds.width } // 替换原有代码中的UIScreen调用 ZStack { AsyncImage(url: URL(string: url)) { image in image } placeholder: { EmptyView() } .frame(maxWidth: currentScreenWidth) buttons }
如果想更优雅地复用这个尺寸,可以扩展环境变量,把屏幕宽度注入到全局环境中:
// 先添加扩展代码 private struct ScreenWidthKey: EnvironmentKey { static let defaultValue: CGFloat = 375 } extension EnvironmentValues { var screenWidth: CGFloat { get { guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene else { return self[ScreenWidthKey.self] } return windowScene.screen.bounds.width } set { self[ScreenWidthKey.self] = newValue } } } // 在视图中调用 @Environment(\.screenWidth) private var screenWidth ZStack { AsyncImage(url: URL(string: url)) { image in image } placeholder: { EmptyView() } .frame(maxWidth: screenWidth) buttons }
方案说明
- 两种方式都能准确获取当前屏幕宽度,完美替代弃用的
UIScreen.main - 限制
AsyncImage的maxWidth后,ZStack的尺寸会被约束在屏幕范围内,按钮就能稳定固定在屏幕角落 - 图片未设置缩放属性(比如
.resizable()),会保持原尺寸自然超出屏幕显示
内容的提问来源于stack exchange,提问作者Rahul Bir
相关产品推荐
相关产品推荐

