共享 SwiftUI 视图的屏幕截图导致崩溃

编程入门 行业动态 更新时间:2024-10-15 06:19:28
本文介绍了共享 SwiftUI 视图的屏幕截图导致崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我正在我的 SwiftUI 视图中抓取子视图的屏幕截图,以立即传递到共享表以共享图像.

该视图是来自呈现为一叠卡片的文本数组的一组问题.我正在尝试获取问题的屏幕截图,并将其与应用链接一起共享(使用指向愤怒的小鸟的链接进行测试).

我已经能够基本上使用 Asperi 对以下问题的回答来捕获屏幕截图:

这是我用来渲染图像的 View 和 UIView 扩展:

扩展 UIView {func asImage() ->用户界面{让渲染器 = UIGraphicsImageRenderer(bounds: bounds)返回 renderer.image { rendererContext inlayer.render(在:rendererContext.cgContext)}}}扩展视图{func asImage() ->用户界面{让控制器 = UIHostingController(rootView: self)//定位到屏幕外controller.view.frame = CGRect(x: 0, y: CGFloat(Int.max), width: 1, height: 1)UIApplication.shared.windows.first!.rootViewController?.view.addSubview(controller.view)让 size = controller.sizeThatFits(in: UIScreen.main.bounds.size)controller.view.bounds = CGRect(origin: .zero, size: size)控制器.view.sizeToFit()controller.view.backgroundColor = .clear让图像 = controller.view.asImage()controller.view.removeFromSuperview()返回图像}}

这是我的视图的缩写版本 - 按钮大约在中间位置,应该调用底部的私有函数,该函数从 View/UIView 扩展中呈现图像,并设置questionScreenShot"渲染图像的变量,然后呈现在共享表中.

struct TopicPage:查看{var currentTopic:主题@State 私有变量 currentQuestions: [String]@State private var showShareSheet = false@State var questionScreenShot: UIImage?= 零var主体:一些视图{GeometryReader { 几何输入按钮(动作:{self.questionScreenShot = render()如果 self.questionScreenShot != nil {self.showShareSheet = true} 别的 {打印(没有设置截图")}}) {文本(分享问题").粗体()}.sheet(isPresented: $showShareSheet) {ShareSheet(activityItems: [questionScreenShot!])}}}私有函数渲染()->用户界面{QuestionBox(currentQuestion: self.currentQuestions[0]).asImage()}}

解决方案

我找到了一个似乎在这里有效的解决方案.我开始将 questionScreenShot 存储为 nil 的变量启动:

@State var questionScreenShot: UIImage?= 零

然后我确保在视图出现时将其设置为渲染",这意味着它会加载 UIImage,因此如果用户点击分享问题"它将准备好加载(我认为之前存在一个问题,即共享完成后 UIImage 没有及时加载).

它还会在消失时将该变量设置回 nil.

.onAppear {self.currentQuestions = currentTopic.questions.shuffled()self.featuredQuestion = currentQuestions.last!self.questionScreenShot = render()}.onDisappear {self.questionScreenShot = nilself.featuredQuestion = nil}

I am grabbing a screenshot of a sub-view in my SwiftUI View to immediately pass to a share sheet in order to share the image.

The view is of a set of questions from a text array rendered as a stack of cards. I am trying to get a screenshot of the question and make it share-able along with a link to the app (testing with a link to angry birds).

I have been able to capture the screenshot using basically Asperi's answer to the below question: How do I render a SwiftUI View that is not at the root hierarchy as a UIImage?

My share sheet launches, and I've been able to use the "Copy" feature to copy the image, so I know it's actually getting a screenshot, but whenever I click "Message" to send it to someone, or if I just leave the share sheet open, the app crashes.

The message says it's a memory issue, but doesn't give much description of the problem. Is there a good way to troubleshoot this sort of thing? I assume it must be something with how the screenshot is being saved in this case.

Here are my extensions of View and UIView to render the image:

extension UIView { func asImage() -> UIImage { let renderer = UIGraphicsImageRenderer(bounds: bounds) return renderer.image { rendererContext in layer.render(in: rendererContext.cgContext) } } } extension View { func asImage() -> UIImage { let controller = UIHostingController(rootView: self) // locate far out of screen controller.view.frame = CGRect(x: 0, y: CGFloat(Int.max), width: 1, height: 1) UIApplication.shared.windows.first!.rootViewController?.view.addSubview(controller.view) let size = controller.sizeThatFits(in: UIScreen.main.bounds.size) controller.view.bounds = CGRect(origin: .zero, size: size) controller.view.sizeToFit() controller.view.backgroundColor = .clear let image = controller.view.asImage() controller.view.removeFromSuperview() return image } }

Here's an abbreviated version of my view - the button is about halfway down, and should call the private function at the bottom that renders the image from the View/UIView extensions, and sets the "questionScreenShot" variable to the rendered image, which is then presented in the share sheet.

struct TopicPage: View { var currentTopic: Topic @State private var currentQuestions: [String] @State private var showShareSheet = false @State var questionScreenShot: UIImage? = nil var body: some View { GeometryReader { geometry in Button(action: { self.questionScreenShot = render() if self.questionScreenShot != nil { self.showShareSheet = true } else { print("Did not set screenshot") } }) { Text("Share Question").bold() } .sheet(isPresented: $showShareSheet) { ShareSheet(activityItems: [questionScreenShot!]) } } } private func render() -> UIImage { QuestionBox(currentQuestion: self.currentQuestions[0]).asImage() } }

解决方案

I've found a solution that seems to be working here. I start the variable where the questionScreenShot gets stored as nil to start:

@State var questionScreenShot: UIImage? = nil

Then I just make sure to set it to 'render' when the view appears, which means it loads the UIImage so if the user clicks "Share Question" it will be ready to be loaded (I think there was an issue earlier where the UIImage wasn't getting loaded in time once the sharing was done).

It also sets that variable back to nil on disappear.

.onAppear { self.currentQuestions = currentTopic.questions.shuffled() self.featuredQuestion = currentQuestions.last! self.questionScreenShot = render() } .onDisappear { self.questionScreenShot = nil self.featuredQuestion = nil }

更多推荐

共享 SwiftUI 视图的屏幕截图导致崩溃

本文发布于:2023-11-30 03:37:27,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1648592.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:视图   截图   屏幕   SwiftUI

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!