iOS 16后如何替代已废弃的UIScreen.main.scale?
替代废弃的
UIScreen.main.scale的方案(含应用扩展兼容) iOS 16 之后,
UIScreen.main.scale已被废弃,UIKit 中 UIScreen 的文档标注如下:@available(iOS, introduced: 2.0, deprecated: 100000, message: "Use a UIScreen instance found through context instead: i.e, view.window.windowScene.screen") open class var main: UIScreen { get } // the device's internal screen其中
deprecated: 100000表示该API已被废弃。现有主应用可行的替代方案依赖UIApplication.shared,无法在应用扩展中使用,以下是分场景的解决方案:
一、主应用中的替代实现
你提供的代码可以在主应用中正常获取当前屏幕,但因依赖UIApplication.shared,无法在应用扩展中运行:
@available(iOSApplicationExtension, unavailable) extension UIWindow { static var current: UIWindow? { for scene in UIApplication.shared.connectedScenes { guard let windowScene = scene as? UIWindowScene else { continue } for window in windowScene.windows { if window.isKeyWindow { return window } } } return nil } } @available(iOSApplicationExtension, unavailable) extension UIScreen { static var current: UIScreen? { UIWindow.current?.screen } }
使用时通过UIScreen.current?.scale即可获取屏幕缩放比例。
二、兼容应用扩展的解决方案
应用扩展无法访问UIApplication.shared,需根据扩展类型从上下文获取UIScreen实例:
1. 带视图的扩展(如今日小组件、自定义键盘)
如果扩展包含视图,直接从视图上下文获取:
extension UIView { var screenScale: CGFloat { self.window?.windowScene?.screen.scale ?? UIScreen.main.scale // 兼容旧系统降级 } }
调用示例:yourView.screenScale
2. 无视图的扩展(如分享扩展、动作扩展)
这类扩展可通过NSExtensionContext获取关联场景,或降级使用旧API(苹果允许扩展中暂时沿用,直到推出替代方案):
// 获取屏幕缩放比例 let scale: CGFloat = { if let scene = NSExtensionContext.shared?.scene as? UIWindowScene { return scene.screen.scale } // 降级到旧API return UIScreen.main.scale }()
3. 通用兼容封装
可以封装一个工具类,自动适配主应用和扩展环境:
enum ScreenScaleProvider { static var scale: CGFloat { // 判断是否为扩展环境 let isExtension = Bundle.main.bundlePath.hasSuffix(".appex") if !isExtension { // 主应用环境 return UIWindow.current?.screen.scale ?? UIScreen.main.scale } else { // 扩展环境 if let scene = NSExtensionContext.shared?.scene as? UIWindowScene { return scene.screen.scale } return UIScreen.main.scale } } } // 主应用中复用你之前的UIWindow扩展 @available(iOSApplicationExtension, unavailable) extension UIWindow { static var current: UIWindow? { for scene in UIApplication.shared.connectedScenes { guard let windowScene = scene as? UIWindowScene else { continue } for window in windowScene.windows { if window.isKeyWindow { return window } } } return nil } } @available(iOSApplicationExtension, unavailable) extension UIScreen { static var current: UIScreen? { UIWindow.current?.screen } }
使用时直接调用ScreenScaleProvider.scale即可在主应用和扩展中通用。
内容的提问来源于stack exchange,提问作者violethill
相关产品推荐
相关产品推荐

