我知道你可以按照这些步骤将iOS SwiftUI
有人知道如何快照/截屏macOS SwiftUI View吗?
View
转换成图像,但在SwiftUI for macOS中,这会使用SwiftUI扩展中不能使用的UIKit元素。有人知道如何快照/截屏macOS SwiftUI View吗?
NSHostingController
是 UIHostingController
的类比版本。此外,要使其绘制视图,应将该视图添加到某个窗口中:extension View {
func snapshot() -> NSImage? {
let controller = NSHostingController(rootView: self)
let targetSize = controller.view.intrinsicContentSize
let contentRect = NSRect(origin: .zero, size: targetSize)
let window = NSWindow(
contentRect: contentRect,
styleMask: [.borderless],
backing: .buffered,
defer: false
)
window.contentView = controller.view
guard
let bitmapRep = controller.view.bitmapImageRepForCachingDisplay(in: contentRect)
else { return nil }
controller.view.cacheDisplay(in: contentRect, to: bitmapRep)
let image = NSImage(size: bitmapRep.size)
image.addRepresentation(bitmapRep)
return image
}
}
controller.view.cacheDisplay
开始的所有内容放入一个DispatchQueue.main.async
块中,并通过完成处理程序返回结果。目前,我还在硬编码targetSize
,因为我的视图没有返回正确的intrinsicContentSize
,但这是一个无关的问题。 - undefined.frame(...)
显式设置视图的大小,那么不仅intrinsicContentSize
有效,而且你还可以调用window.contentView?.layout()
(没有定义大小也不会崩溃)使其在不使用DispatchQueue.main.async
的情况下正常工作。 - undefined使用SwiftUI的ImageRenderer对象将macOS视图光栅化为NSImage。
以下是代码:
import SwiftUI
@MainActor final class BitmapImage : ObservableObject {
@Published var images: [String: NSImage] = [:]
init() {
let view = SampleView()
let renderer = ImageRenderer(content: view)
#if os(macOS)
renderer.scale = NSApplication.shared
.mainWindow?
.backingScaleFactor ?? 2.0
if let nsImage = renderer.nsImage {
images["1"] = nsImage
}
#endif
}
}
struct SampleView : View {
var body: some View {
ZStack {
Image("picture")
VStack {
Divider()
Text("Lorem ipsum dolor sit amet")
.foregroundColor(.white)
.font(.custom("", size: 72))
Spacer()
}
}
}
}
@available(macOS 13.0, *) struct ContentView : View {
@StateObject private var bitmapImage = BitmapImage()
var body: some View {
ZStack {
if let nsImage = bitmapImage.images["1"] {
Image(nsImage: nsImage)
.resizable()
.frame(width: 500) // "Squeezed" Image test
}
}
}
}