在开发“轻压图片”时,我想要点击上传的缩略图(Image类型),显示原图。

问题思路有两种:
1、创建NSWindow显示原图预览。
2、使用Quick Look查看图片。
下面将对这两种思路进行详细的介绍。
一、NSWindow显示大图
1、创建NSWindows窗口类
import AppKit
import SwiftUI
class ImagePreviewWindow {
private var window: NSWindow?
func show(image: Image) {
let hostingView = NSHostingView(rootView:
image
.resizable()
.scaledToFit()
.frame(minWidth: 400, minHeight: 400)
.padding()
)
let window = NSWindow(contentViewController: NSViewController())
window.contentView = hostingView
window.title = "Image Preview"
window.setContentSize(NSSize(width: 600, height: 600))
window.styleMask = [.titled, .closable, .resizable]
window.center()
window.makeKeyAndOrderFront(nil)
self.window = window
}
}
2、在 SwiftUI 视图中使用
image
.resizable()
.scaledToFit()
.frame(width: 100, height: 100)
.onTapGesture {
previewer.show(image: image)
}
通过onTapGesture点击手势,创建NSWindow窗口并显示图片。

二、使用 Quick Look 预览
1、实现QLPreviewItem 和 QLPreviewPanelDataSource
import QuickLook
import QuickLookUI
class PreviewItem: NSObject, QLPreviewItem {
var previewItemURL: URL?
var previewItemTitle: String?
init(url: URL) {
self.previewItemURL = url
self.previewItemTitle = url.lastPathComponent
}
}
class PreviewDataSource: NSObject, QLPreviewPanelDataSource {
var items: [PreviewItem]
init(urls: [URL]) {
self.items = urls.map { PreviewItem(url: $0) }
}
func numberOfPreviewItems(in panel: QLPreviewPanel!) -> Int {
items.count
}
func previewPanel(_ panel: QLPreviewPanel!, previewItemAt index: Int) -> QLPreviewItem! {
items[index]
}
}
2、使用Quick Look打开图片
func previewImage(at url: URL) {
guard let panel = QLPreviewPanel.shared() else { return }
let dataSource = PreviewDataSource(urls: [url])
panel.dataSource = dataSource
panel.makeKeyAndOrderFront(nil)
}
3、在SwiftUI视图中调用
.onTapGesture {
previewImage(at: imageURL) // 必须有实际 URL,不能是 NSImage
}
Quick Look 只能预览 URL 文件,不能直接预览 NSImage。
所以必须将 NSImage 保存为临时文件再预览。
4、临时保存NSImage为URL示例:
func saveImageToTempFile(image: NSImage) -> URL? {
guard let tiffData = image.tiffRepresentation,
let bitmap = NSBitmapImageRep(data: tiffData),
let pngData = bitmap.representation(using: .png, properties: [:]) else {
return nil
}
let tempURL = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString + ".png")
try? pngData.write(to: tempURL)
return tempURL
}
然后调用:
if let url = saveImageToTempFile(image: images[index]) {
previewImage(at: url)
}

总结
使用macOS显示原图预览,可以通过新建窗口显示原图,简单并且支持NSImage,缺点是需要自己管理窗口。
也可以使用Quick Look预览,原生强大(支持PDF/GIF),但是只能用文件URL(要保存图片)。
如果想要实现多图预览,ESC退出、导航操作,建议使用Quick Look。