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

SwiftUI中如何截取包含状态栏的全屏截图?

问题与解决方案

问题描述

我编写了一个SwiftUI View的扩展函数用于生成视图截图,但生成的结果里没有包含状态栏,不符合预期。代码如下:

extension View {
    func snapshot() -> UIImage {
        let size = CGSizeMake(UIScreen.main.bounds.width,UIScreen.main.bounds.height)
        let controller = UIHostingController(rootView: self.ignoresSafeArea())
        let view = controller.view
        view?.bounds = CGRect(origin: .zero, size: size)
        let renderer = UIGraphicsImageRenderer(size: size)
        return renderer.image { _ in
            view?.drawHierarchy(in:CGRect(origin: .zero, size: size), afterScreenUpdates: true)
        }
    }
}

解决方案

方案1:截取当前屏幕(包含系统状态栏)

如果你的视图已经在屏幕上显示,直接截取当前活跃窗口的内容可以完整包含状态栏:

extension View {
    func snapshotWithStatusBar() -> UIImage? {
        guard let keyWindow = UIApplication.shared.connectedScenes
                .filter({ $0.activationState == .foregroundActive })
                .compactMap({ $0 as? UIWindowScene })
                .first?.windows
                .first(where: { $0.isKeyWindow }) else {
            return nil
        }
        
        let renderer = UIGraphicsImageRenderer(size: keyWindow.bounds.size)
        return renderer.image { context in
            keyWindow.drawHierarchy(in: keyWindow.bounds, afterScreenUpdates: true)
        }
    }
}

方案2:模拟状态栏渲染(适用于视图未显示时)

如果视图还未在屏幕上展示,需要渲染出带状态栏的截图,可以手动添加模拟状态栏到UIHostingController中:

extension View {
    func snapshotWithStatusBar() -> UIImage {
        let screenSize = UIScreen.main.bounds.size
        let statusBarHeight = UIApplication.shared.statusBarFrame.height
        
        // 创建HostingController,保留安全区布局
        let controller = UIHostingController(rootView: self)
        let hostView = controller.view!
        hostView.frame = CGRect(origin: .zero, size: screenSize)
        
        // 添加匹配系统样式的状态栏视图
        let statusBarView = UIView(frame: CGRect(x: 0, y: 0, width: screenSize.width, height: statusBarHeight))
        statusBarView.backgroundColor = UIApplication.shared.statusBarStyle == .darkContent ? .white : .black
        hostView.addSubview(statusBarView)
        
        let renderer = UIGraphicsImageRenderer(size: screenSize)
        return renderer.image { _ in
            hostView.drawHierarchy(in: hostView.bounds, afterScreenUpdates: true)
        }
    }
}

说明

  • 方案1针对已显示在屏幕上的视图,直接截取当前窗口内容,能完整保留系统状态栏、导航栏等所有屏幕元素。
  • 方案2针对未展示的视图,手动模拟状态栏样式,可根据App主题调整状态栏的背景色和样式。

内容的提问来源于stack exchange,提问作者Gopala Krishnan S

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 21:46:05