将 SwiftUI 视图渲染为 UIImage [英] Render SwiftUI View as an UIImage

查看:63
本文介绍了将 SwiftUI 视图渲染为 UIImage的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将 SwiftUI 视图呈现为 UIImage,然后让用户选择保存到相机胶卷或通过电子邮件发送给其他人.

I'm trying to render the SwiftUI View as an UIImage then let the user choose to save to the camera roll or send to others via email.

举个例子,我想将一个 50 行的列表渲染到一个 UIImage 中.

As an example, I want to render a list of 50 rows into a UIImage.

struct MyList: View {
    var body: some View {
        List {
            ForEach(0 ..< 50, id:\.self) {
                Text("row \($0)")
            }
        }
    }
}

过去几周在互联网上搜索仍然没有运气.我尝试了 2 种不同的方法.

Searched over the internet for the past few weeks still with no luck. I have tried 2 different approaches.

1.UIHostingController(来源)

let hosting = UIHostingController(rootView: Text("TEST"))
hosting.view.frame = // Calculate the content size here //
let snapshot = hosting.view.snapshot        // output: an empty snapshot of the size
print(hosting.view.subviews.count)          // output: 0

我试过layoutSubviews()setNeedsLayout()layoutIfNeeded()loadView(),但仍然产生了 0 个子视图.

I've tried layoutSubviews(), setNeedsLayout(), layoutIfNeeded(), loadView(), but all still resulted 0 subviews.

2.UIWindow.rootViewController(来源在这里一>)

var vc = UIApplication.shared.windows[0].rootViewController
vc = vc.visibleController          // loop through the view controller stack to find the top most view controller
let snapshot = vc.view.snapshot    // output: a snapshot of the top most view controller

这几乎产生了我想要的输出.但是,我得到的快照实际上是一个屏幕截图,即带有导航栏、标签栏和固定大小(与屏幕大小相同).我需要捕获的只是没有这些条的视图内容,有时可能比屏幕大(在这个例子中我的视图是一个长列表).

This almost yields the output I have wanted. However, the snapshot I get is literally a screenshot, i.e. with a Navigation bar, Tab bar and fixed size (same as screen size). What I need to capture is simply the view's content without those bars, and may sometimes be larger than the screen (my view is a long list in this example).

试过查询<代码> vc.view.subviews 寻找我想要的表视图,但返回一个无用<代码>并[d _TtGC7SwiftUI16PlatformViewHostGVS_42PlatformViewControllerRepresentableAdaptorGVS_16BridgedSplitViewVVS_22_VariadicView_Children7ElementGVS_5GroupGVS_19_ConditionalContentS4_GVS_17_UnaryViewAdaptorVS_9EmptyView ______:0x7fb061cc4770;帧 = (0 0; 414 842);锚点 = (0, 0);tintColor = UIExtendedSRGBColorSpace 0 0.478431 1 1;layer = <CALayer: 0x600002d8caa0>>].

Tried to query vc.view.subviews to look for the table view I want, but returning an unhelpful [<_TtGC7SwiftUI16PlatformViewHostGVS_42PlatformViewControllerRepresentableAdaptorGVS_16BridgedSplitViewVVS_22_VariadicView_Children7ElementGVS_5GroupGVS_19_ConditionalContentS4_GVS_17_UnaryViewAdaptorVS_9EmptyView______: 0x7fb061cc4770; frame = (0 0; 414 842); anchorPoint = (0, 0); tintColor = UIExtendedSRGBColorSpace 0 0.478431 1 1; layer = <CALayer: 0x600002d8caa0>>].

非常感谢任何帮助.

推荐答案

这样的事情对你有用吗?

import SwiftUI

extension UIView {
    func takeScreenshot() -> UIImage {
        // Begin context
        UIGraphicsBeginImageContextWithOptions(self.bounds.size, false, UIScreen.main.scale)
        // Draw view in that context
        drawHierarchy(in: self.bounds, afterScreenUpdates: true)
        // And finally, get image
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        if (image != nil) {
            UIImageWriteToSavedPhotosAlbum(image!, nil, nil, nil);
            return image!
        }

        return UIImage()
    }
}

struct ContentView: UIViewRepresentable {
    func makeUIView(context: Context) -> UIView {
        let someView = UIView(frame: UIScreen.main.bounds)
        _ = someView.takeScreenshot()
        return someView
    }

    func updateUIView(_ view: UIView, context: Context) {

    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

这篇关于将 SwiftUI 视图渲染为 UIImage的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆