【问题标题】:UIImage from View with onAppear logic来自 View 的 UIImage 与 onAppear 逻辑
【发布时间】:2021-10-16 09:13:10
【问题描述】:

当我在 View 的 onAppear 中有任何逻辑时,我无法将 SwiftUI View 渲染为 UIImage。

例如,这里我们有一个SnapshotViewTest,它有一个Button,应该制作AGreatView 的快照并显示UIImage 结果。 AGreatView 仅在 onAppear 上具有逻辑 - 将 Color.green 的 width 设置为我希望在屏幕上显示的 50。

它应该是这样的:

它是这样的:

这里是SnapshotViewTest:

struct SnapshotViewTest: View {
    @State var uiImage = UIImage()
    var body: some View {
        VStack {
            Button("Make a snapshot of a great view", action: {
                let view = AGreatView()
                
                uiImage = view.animation(nil).snapshot()
            })
            Image(uiImage: uiImage)
        }
    }
    
    struct AGreatView: View {
        @State var width = 0.0
        var body: some View {
            VStack {
                Text("Some text")
                Color.green.frame(width: width, height: 10) //works when I set "width" to any Double
            }.padding()
                .background(Color.red.opacity(0.1))
            .onAppear {
                DispatchQueue.main.async { //does not make any difference without
                    width = 50
                }
            }
        }
    }
}

这是我的观点snapshot func:

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)
                
        let renderer = UIGraphicsImageRenderer(size: targetSize)
        
        return renderer.image { _ in
            view?.drawHierarchy(in: controller.view.bounds, afterScreenUpdates: true)
        }
        
    }
}

感谢您的任何想法!

【问题讨论】:

    标签: swiftui uikit uiimage


    【解决方案1】:

    你可以试试这个,对我有用:

    Button("Make a snapshot of a great view", action: {
        let view = AGreatView()
        DispatchQueue.main.async {
            uiImage = view.snapshot()
        }
    })
    

    在AGreatView onAppear 中不需要DispatchQueue。

    如果这仍然不适合您,请尝试引入一点延迟,例如:

    DispatchQueue.main.asyncAfter(deadline: .now() + 0.1)
    

    【讨论】:

    • 不错!我对它为什么起作用感到困惑,因为视图以快照函数呈现,但它起作用。但是,我仍然需要让 DispatchQueue.main.async 正常工作(在我的示例中不需要它,但我的应用程序中有一个异步调用并且需要一些延迟 - 先渲染视图,等待,然后制作照片) .但我的尝试没有成功。
    猜你喜欢
    • 2012-09-30
    • 1970-01-01
    • 2023-04-07
    • 2013-02-18
    • 2021-12-27
    • 2023-03-15
    • 2013-06-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多