iOS 13应用进入后台时显示自定义启动屏:原方案失效如何修复?
嘿,我正好研究过这个问题!iOS13引入SceneDelegate后,原来在AppDelegate里那套后台截屏拦截方案就失效了——毕竟现在每个Scene都有独立的生命周期,得把逻辑移到SceneDelegate里才行。下面是具体的修复方案:
iOS13 修复后台自定义启动屏(多任务显示白屏)的方案
核心思路
系统在应用进入后台时,会对当前界面截屏作为多任务预览图。我们要做的就是在系统截屏前显示自定义遮罩视图(比如白屏),等截屏完成后再移除它,这样多任务界面就只会展示我们想要的内容了。
具体实现步骤
1. 把逻辑转移到SceneDelegate中
iOS13+的场景生命周期由SceneDelegate管理,所以我们要在sceneDidEnterBackground方法里添加遮罩视图:
class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? // 保存遮罩视图引用,方便后续移除 private var backgroundSnapshotMask: UIView? func sceneDidEnterBackground(_ scene: UIScene) { guard let windowScene = scene as? UIWindowScene, let mainWindow = windowScene.windows.first else { return } // 创建全屏白屏遮罩 let maskView = UIView(frame: mainWindow.bounds) maskView.backgroundColor = .white maskView.tag = 999 // 标记视图,方便后续查找(可选) mainWindow.addSubview(maskView) backgroundSnapshotMask = maskView // 强制刷新界面,确保系统截屏时能捕获到这个视图 maskView.layoutIfNeeded() mainWindow.layoutIfNeeded() } func sceneWillEnterForeground(_ scene: UIScene) { // 回到前台时移除遮罩 backgroundSnapshotMask?.removeFromSuperview() backgroundSnapshotMask = nil } }
2. 兼容iOS13以下版本(可选)
如果你的App还要支持iOS12及以下,记得在AppDelegate里保留旧逻辑做兼容:
@UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? private var backgroundSnapshotMask: UIView? func applicationDidEnterBackground(_ application: UIApplication) { if #available(iOS 13.0, *) { // iOS13+交给SceneDelegate处理 return } // iOS12及以下的遮罩逻辑 let maskView = UIView(frame: window?.bounds ?? .zero) maskView.backgroundColor = .white window?.addSubview(maskView) backgroundSnapshotMask = maskView window?.layoutIfNeeded() } func applicationWillEnterForeground(_ application: UIApplication) { if #available(iOS 13.0, *) { return } backgroundSnapshotMask?.removeFromSuperview() backgroundSnapshotMask = nil } }
为什么旧方案失效?
iOS13之前整个App只有一个窗口和统一的生命周期,applicationDidEnterBackground能全局触发。但iOS13引入了多Scene支持(比如iPad分屏、多窗口),每个Scene有独立的生命周期回调,原来在AppDelegate里添加的视图,系统截屏时可能无法捕获到当前活跃Scene的窗口内容。
注意事项
- 遮罩视图一定要添加到当前Scene的主Window上,不要用全局Window或者其他非活跃窗口,否则系统截屏可能抓不到。
- 必须调用
layoutIfNeeded()强制刷新界面,确保遮罩视图已经渲染完成,不然截屏可能还是原来的界面。 - 如果想要自定义其他样式(比如加logo、特定背景色),只需要修改
maskView的属性或者添加子视图即可。
内容的提问来源于stack exchange,提问作者Vyachaslav Gerchicov
相关产品推荐
相关产品推荐

