把SwiftUI View 转为图片

方法1: 使用 drawHierarchy

swift 复制代码
extension View {
    func snapshot() -> UIImage {
        let controller = UIHostingController(rootView: self)
        let view = controller.view

        let targetSize = controller.view.intrinsicContentSize
        view?.bounds = CGRect(origin: .zero, size: targetSize)
        view?.backgroundColor = .clear

        let renderer = UIGraphicsImageRenderer(size: targetSize)

        return renderer.image { _ in
            view?.drawHierarchy(in: controller.view.bounds, afterScreenUpdates: true)
        }
    }
}

注意:这个方法需要swiftUI view 设置 .edgesIgnoringSafeArea(.all)

完整demo:

swift 复制代码
struct ContentView: View {
    var textView: some View {
        VStack{
            Text("ABCSF1")
            Text("ABCSF2")
            Text("ABCSF3")
            Text("Hello, SwiftUI")
                .padding()
                .background(.blue)
                .foregroundStyle(.white)
                .clipShape(Capsule())
        }
        .edgesIgnoringSafeArea(.all)
    }

    var body: some View {
        VStack {
            textView

            Button("Save to image") {
                let image = textView.snapshot()

                UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
            }
        }
        .edgesIgnoringSafeArea(.all)

    }
}

extension View {
    func snapshot() -> UIImage {
        let controller = UIHostingController(rootView: self)
        let view = controller.view

        let targetSize = controller.view.intrinsicContentSize
        view?.bounds = CGRect(origin: .zero, size: targetSize)
        view?.backgroundColor = .clear

        let renderer = UIGraphicsImageRenderer(size: targetSize)

        return renderer.image { _ in
            view?.drawHierarchy(in: controller.view.bounds, afterScreenUpdates: true)
        }
    }
}

方法2: 使用ImageRenderer,需要iOS16以上

less 复制代码
struct RenderView: View {
    let text: String

    var body: some View {
        Text(text)
            .font(.largeTitle)
            .foregroundStyle(.white)
            .padding()
            .background(.blue)
            .clipShape(Capsule())
    }
}

struct ContentView: View {
    @State private var text = "Your text here"
    @State private var renderedImage = Image(systemName: "photo")
    @Environment(\.displayScale) var displayScale

    var body: some View {
        VStack {
            renderedImage

            ShareLink("Export", item: renderedImage, preview: SharePreview(Text("Shared image"), image: renderedImage))

            TextField("Enter some text", text: $text)
                .textFieldStyle(.roundedBorder)
                .padding()
        }
        .onChange(of: text) { _ in render() }
        .onAppear { render() }
    }

    @MainActor
    func render() {
        let renderer = ImageRenderer(content: RenderView(text: text))
        
        // make sure and use the correct display scale for this device
        renderer.scale = displayScale

        if let uiImage = renderer.uiImage {
            renderedImage = Image(uiImage: uiImage)
        }
    }
}

参考文章:

www.hackingwithswift.com/quick-start...

swdevnotes.com/swift/2022/...

相关推荐
文件夹__iOS2 小时前
AsyncStream 进阶实战:SwiftUI 全局消息流极简实现
ios·swiftui·swift
2501_916008894 小时前
深入解析iOS机审4.3原理与混淆实战方法
android·java·开发语言·ios·小程序·uni-app·iphone
忆江南4 小时前
Flutter深度全解析
ios
山水域4 小时前
Swift 6 严格并发检查:@Sendable 与 Actor 隔离的深度解析
ios
楚轩努力变强5 小时前
iOS 自动化环境配置指南 (Appium + WebDriverAgent)
javascript·学习·macos·ios·appium·自动化
游戏开发爱好者81 天前
日常开发与测试的 App 测试方法、查看设备状态、实时日志、应用数据
android·ios·小程序·https·uni-app·iphone·webview
黑码哥1 天前
ViewHolder设计模式深度剖析:iOS开发者掌握Android列表性能优化的实战指南
android·ios·性能优化·跨平台开发·viewholder
2501_915106321 天前
app 上架过程,安装包准备、证书与描述文件管理、安装测试、上传
android·ios·小程序·https·uni-app·iphone·webview
2501_915106321 天前
使用 Sniffmaster TCP 抓包和 Wireshark 网络分析
网络协议·tcp/ip·ios·小程序·uni-app·wireshark·iphone
熊猫钓鱼>_>1 天前
移动端开发技术选型报告:三足鼎立时代的开发者指南(2026年2月)
android·人工智能·ios·app·鸿蒙·cpu·移动端