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

iOS中UIAlertController为顶层控制器时,如何通过代码截取应用屏幕?

解决iOS截取含UIAlertController弹窗的屏幕问题

原代码的问题在于:UIAlertController的弹窗并非嵌套在顶层控制器的view层级中,而是直接附加在应用的**主窗口(keyWindow)**上。所以只渲染顶层控制器的view,只能捕获弹窗本身或者底层页面,无法同时获取两者。

要实现包含弹窗且不含状态栏的全屏截取,直接从主窗口入手即可,以下是修改后的代码:

extension UIViewController {
    static func takeScreenshotWithoutStatusBar() -> UIImage? {
        // 兼容iOS 13+多场景,获取当前活跃的主窗口
        let window: UIWindow?
        if #available(iOS 13.0, *) {
            window = UIApplication.shared.connectedScenes
                .filter { $0.activationState == .foregroundActive }
                .compactMap { $0 as? UIWindowScene }
                .first?
                .windows
                .first(where: { $0.isKeyWindow })
        } else {
            window = UIApplication.shared.keyWindow
        }
        
        guard let mainWindow = window else { return nil }
        
        // 计算不含状态栏的区域
        var captureBounds = mainWindow.bounds
        let statusBarHeight: CGFloat
        if #available(iOS 13.0, *) {
            statusBarHeight = mainWindow.windowScene?.statusBarManager?.statusBarFrame.height ?? 0
        } else {
            statusBarHeight = UIApplication.shared.statusBarFrame.height
        }
        // 下移起始点并缩短高度,排除状态栏
        captureBounds.origin.y += statusBarHeight
        captureBounds.size.height -= statusBarHeight
        
        UIGraphicsBeginImageContextWithOptions(captureBounds.size, false, UIScreen.main.scale)
        defer { UIGraphicsEndImageContext() }
        
        guard let context = UIGraphicsGetCurrentContext() else { return nil }
        
        // 偏移上下文坐标,确保只捕获目标区域
        context.translateBy(x: -captureBounds.origin.x, y: -captureBounds.origin.y)
        // 渲染整个窗口的内容,包含所有层级(弹窗、页面等)
        mainWindow.layer.render(in: context)
        
        return UIGraphicsGetImageFromCurrentImageContext()
    }
}

代码说明:

  • 窗口获取:适配iOS 13+的多场景机制,确保拿到当前前台活跃的keyWindow,避免在多场景应用中取错窗口
  • 区域调整:通过计算状态栏高度,精准截取窗口中除状态栏外的部分
  • 全层级渲染:直接渲染主窗口的layer,所有挂载在窗口上的UI元素(包括UIAlertController弹窗、悬浮视图等)都会被包含在截图中

如果需要截取包含状态栏的完整屏幕,只需要移除captureBounds的调整代码,直接使用mainWindow.bounds即可。

内容的提问来源于stack exchange,提问作者Rehan Ali Khan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 06:45:01