在启动尝试共享该图像的表格之前,是否有办法确保图像(应用程序的屏幕截图)已渲染?
我要启动一个共享表,该共享表在显示一叠纸牌的视图中使用当前的“纸牌”,然后对存储在变量“ questionScreenShot”中的纸牌截屏。该卡应该与链接一起共享-我正在使用来自这个问题的Asperi解决方案的一种变体来生成图像: How do I render a SwiftUI View that is not at the root hierarchy as a UIImage?
我第一次单击“共享问题”按钮时,该卡不共享(我仅获得链接)。但是,如果我继续运行该应用程序,然后再次单击“共享问题”,那么我会得到一个图像。
我有一个if语句,仅当图像具有值时才应该启动共享表。在ShareSheet启动之前,我有断点,断点应该朝不同的方向进行,因为根据下图中“ questionScreenShot”的值,该图像似乎仍然为空。
但是,当应用程序实际启动工作表时,它说我的打印输出中的图像有一些价值:
sharesheet has some value
sharesheet equals Optional(<UIImage:0x282fdb330 anonymous {300, 380}>)
这是我的文件,带有生成图像的视图扩展名:
import SwiftUI
import UIKit
extension UIView {
func asImage() -> UIImage {
let renderer = UIGraphicsImageRenderer(bounds: bounds)
return renderer.image { rendererContext in
self.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
}
}
这是我的页面结构,带有共享表单按钮,以及仅在image var具有值的情况下才应该启动共享表单的if语句:
struct TopicPage: View {
//inherit current topic from the PackTopics page, and create a state variable that gets set to a random question.
var currentTopic: Topic
@State private var currentQuestions: [String]
@State private var showShareSheet = false
@State private var rect: CGRect = .zero
let appURL: String = "https://apps.apple.com/us/app/im-curious/id1518506383"
@State var questionScreenShot: UIImage? = nil
@State var shareQuestionVisible: Bool = true
var body: some View {
GeometryReader { geometry in
Blah Blah Blah
Spacer()
.sheet(isPresented: $showShareSheet, onDismiss: {
questionScreenShot = nil
print("Question Screenshot reset to \(questionScreenShot ?? nil)")
}) {
ShareSheet(activityItems: [questionScreenShot ?? nil, appURL])
}
}
//Set the background image.
.navigationBarItems(trailing:
Button(action: {
self.questionScreenShot = render()
if self.questionScreenShot != nil {
print("sharesheet has some value")
print("sharesheet equals \(questionScreenShot)")
self.showShareSheet = true
} else {
print("Did not set screenshot")
}
}) {
Text("Share Question").bold()
}.disabled(!shareQuestionVisible)
)
}
// Geometry Reader ignores all safe edges
.edgesIgnoringSafeArea(.all)
}
func removeQuestion(at question: Int) {
currentQuestions.remove(at: question)
if currentQuestions.count == 0 {
self.shareQuestionVisible = false
}
}
private func render() -> UIImage {
Card(color: currentTopic.color, text: self.currentQuestions[currentQuestions.count-1]).asImage()
}
}
编辑:刚刚尝试过Asperi的解决方案,将启动共享工作表调用包装在DispatchQueue.main.async中,其行为似乎大致相同:
我尝试更改对ShareSheet的调用以匹配Asperi的建议,其行为大致相同。它不会第一次启动屏幕截图,但是会第二次启动屏幕截图。
Spacer()
.sheet(isPresented: $showShareSheet, onDismiss: {
questionScreenShot = nil
print("Question Screenshot reset to \(questionScreenShot ?? nil)")
}) {
ShareSheet(activityItems: [questionScreenShot ?? nil, appURL])
}
}
//Set the background image.
.navigationBarItems(trailing:
Button(action: {
self.questionScreenShot = render()
print("Question Screenshot now set to \(questionScreenShot ?? nil)")
DispatchQueue.main.async {
self.showShareSheet = true
}
}) {
这是我得到的输出,因此看来第一次和第二次都正确设置了屏幕截图,然后在我关闭共享表时将其重置为nil。我确实收到CFMessagePort错误,但不确定是否与此有关。
Question Screenshot now set to Optional(<UIImage:0x162e24c80 anonymous {300, 380}>)
2020-11-02 07:20:02.917212-0600 Travel Conversation Starters[6492:694831] [PPT] Error creating the CFMessagePort needed to communicate with PPT.
Question Screenshot reset to nil
2020-11-02 07:20:12.731769-0600 Travel Conversation Starters[6492:695053] [ShareSheet] connection invalidated
Question Screenshot now set to Optional(<UIImage:0x162e1b970 anonymous {300, 380}>)
2020-11-02 07:20:20.276303-0600 Travel Conversation Starters[6492:694831] [PPT] Error creating the CFMessagePort needed to communicate with PPT.
注意:我确实更改了结构中的变量,使其指向我的Images.xcassets文件夹中的实际图像,并且它第一次加载了该图像。因此,似乎在第一次加载图像时速度过慢存在一些问题。
@State var questionScreenShot: UIImage? = UIImage(named: "Test")
答案 0 :(得分:0)
这与我对其他问题的回答有关:Sharing Screenshot of SwiftUI view causes crash
但是基本上,我只需要确保在视图中添加了一个OnAppear代码块,该代码块也将shareQuestion图像设置为render()。然后我将其重新设置为视图的OnDisappearnil。