如何在新视图中展示View快照?现有实现快照不显示如何解决?
问题原因
- 快照生成时机错误:你在
sheet的content闭包内执行快照采集,此时系统已经开始执行sheet弹出的过渡动画,原视图层级已经发生状态变更,textView可能已经退出活跃渲染上下文,或者采集到的是状态更新后的空白内容。 - 快照函数缺少布局触发步骤:你创建的
UIHostingController仅设置了bounds,没有手动触发布局计算,intrinsicContentSize大概率会返回CGSize.zero,最终生成的图片是空的透明图,所以展示不出来。
修复方案
第一步:完善快照采集函数
在快照函数中增加布局触发代码,确保视图内容完全渲染后再生成图片:
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 // 新增:手动触发布局计算,确保视图内容完全渲染 view?.layoutIfNeeded() let renderer = UIGraphicsImageRenderer(size: targetSize) return renderer.image { _ in view?.drawHierarchy(in: controller.view.bounds, afterScreenUpdates: true) } } }
第二步:调整快照生成时机
提前在触发sheet弹出的逻辑里生成快照,存入状态变量后再弹出sheet:
- 新增存储快照的状态变量
@State private var capturedImage: UIImage?
- 修改触发sheet的逻辑(以按钮点击为例)
Button("生成并展示快照") { // 先采集快照,再弹出sheet capturedImage = textView.snapshot() showscreenshot = true }
- 修改sheet的内容实现,直接使用预先生成的快照
.sheet(isPresented: $showscreenshot) { if let image = capturedImage { Image(uiImage: image) .resizable() .scaledToFit() .frame(width: 299, height: 299) } }
内容的提问来源于stack exchange,提问作者fatdrogen
相关产品推荐
相关产品推荐

