You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 04:33:07