Swift 4/iOS11中如何用启动屏/图遮挡后台时的应用机密信息?
嘿,这个问题我熟!你想用启动图在后台遮挡机密信息,旧的OC代码在现在的Swift环境里跑不起来,主要是因为iOS的窗口管理逻辑和语法变化,我给你整理了适配iOS11+的Swift实现方案👇
为什么旧OC代码失效了?
- 首先,旧代码是Objective-C语法,直接转Swift会有明显的语法差异,比如OC里的
self.window在Swift里的获取方式已经不同 - 其次,即使是iOS11,窗口的层级管理也有细节变化,旧代码没有考虑重复添加遮挡视图的问题
- 另外,旧代码没有适配不同屏幕尺寸的启动图,容易出现遮挡不全的情况
Swift适配iOS11+的实现方案
第一步:定义工具方法和常量
先在对应的代理类(AppDelegate或SceneDelegate)里定义遮挡视图的标记、启动图获取方法,以及遮挡/移除的核心逻辑:
// 遮挡视图的唯一标记,用于后续移除 private let kLaunchScreenOverlayTag = 1000 // 获取匹配当前屏幕的启动图 private func getLaunchImage() -> UIImage? { let screenSize = UIScreen.main.bounds.size let orientation = UIApplication.shared.statusBarOrientation // 先尝试从Assets的LaunchImage集合中匹配 if let launchImageSet = UIImage(named: "LaunchImage") { for image in launchImageSet.images ?? [] { let imageSize = image.size // 横屏时交换宽高,保证尺寸匹配 let targetSize = orientation.isLandscape ? CGSize(width: imageSize.height, height: imageSize.width) : imageSize if targetSize.equalTo(screenSize) { return image } } } // 如果集合匹配失败,尝试按屏幕尺寸直接匹配命名的图片 let scale = UIScreen.main.scale let imageName = "LaunchImage-\(Int(screenSize.width))x\(Int(screenSize.height))@\(Int(scale))x" return UIImage(named: imageName) } // 添加启动图遮挡层 private func addLaunchScreenOverlay() { // 获取当前活跃的主窗口 let keyWindow = UIApplication.shared.windows.first { $0.isKeyWindow } ?? UIApplication.shared.windows.first guard let window = keyWindow else { return } // 先移除已有的遮挡视图,避免重复添加 removeLaunchScreenOverlay() guard let launchImage = getLaunchImage() else { print("无法获取启动图,遮挡操作失败") return } let overlayView = UIImageView(image: launchImage) overlayView.frame = window.bounds overlayView.tag = kLaunchScreenOverlayTag // 添加到窗口最上层,确保覆盖所有内容 window.addSubview(overlayView) // 强制刷新界面,保证系统后台截图前视图已渲染完成 window.layoutIfNeeded() } // 移除启动图遮挡层 private func removeLaunchScreenOverlay() { let keyWindow = UIApplication.shared.windows.first { $0.isKeyWindow } ?? UIApplication.shared.windows.first guard let window = keyWindow else { return } window.subviews.forEach { subview in if subview.tag == kLaunchScreenOverlayTag { subview.removeFromSuperview() } } }
第二步:在生命周期回调中调用
针对iOS11-12(仅使用AppDelegate)
在AppDelegate.swift里实现后台/前台的回调逻辑:
func applicationDidEnterBackground(_ application: UIApplication) { // 应用进入后台时添加遮挡 addLaunchScreenOverlay() } func applicationWillEnterForeground(_ application: UIApplication) { // 应用回到前台时移除遮挡 removeLaunchScreenOverlay() }
针对iOS13+(使用SceneDelegate)
如果你的项目支持iOS13及以上,需要在SceneDelegate.swift里补充回调:
func sceneDidEnterBackground(_ scene: UIScene) { addLaunchScreenOverlay() } func sceneWillEnterForeground(_ scene: UIScene) { removeLaunchScreenOverlay() }
关键注意事项
- 启动图配置:确保Assets里正确配置了
LaunchImage,包含所有需要适配的屏幕尺寸(iPhone、iPad不同机型) - 窗口获取:用
isKeyWindow筛选活跃窗口,避免获取到非主窗口导致遮挡无效 - 及时移除:必须在应用回到前台时移除遮挡视图,否则会挡住用户操作
- 强制刷新:添加遮挡后调用
layoutIfNeeded(),保证系统在后台截图前视图已经完全显示
这样就能完美实现后台用启动图遮挡机密信息的需求啦!
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

