当 macOS 上的图像发生变化时,SwiftUI onDrag 预览不会更新
SwiftUI onDrag preview doesn't get updated when Image changes on macOS
我在 Image
上有一个 .onDrag
。无论我是否自己提供 preview
,preview
总是卡在显示第一次拖动时出现的 Image
。 NSItemProvider
本身运行良好,我访问了正确的数据,但不在 preview
.
中
一个简单的例子(此处提供代码:https://github.com/godbout/DragPreview)
import SwiftUI
struct AppDetail {
let bundleIdentifier: String
let icon: NSImage
init(bundleIdentifier: String) {
self.bundleIdentifier = bundleIdentifier
if
let url = NSWorkspace.shared.urlForApplication(withBundleIdentifier: bundleIdentifier),
let representation = NSWorkspace.shared.icon(forFile: url.path).bestRepresentation(for: NSRect(x: 0, y: 0, width: 64, height: 64), context: nil, hints: nil)
{
self.icon = NSImage(size: representation.size)
self.icon.addRepresentation(representation)
} else {
self.icon = NSApp.applicationIconImage!
}
}
}
struct ContentView: View {
@State private var apps: [AppDetail] = [
AppDetail(bundleIdentifier: "com.apple.Mail"),
AppDetail(bundleIdentifier: "com.apple.MobileSMS"),
AppDetail(bundleIdentifier: "com.apple.Safari"),
]
var body: some View {
VStack(alignment: .center) {
Image(nsImage: apps.first == nil ? NSApp.applicationIconImage! : apps.first!.icon)
.onDrag {
guard
let app = apps.first,
let url = NSWorkspace.shared.urlForApplication(withBundleIdentifier: app.bundleIdentifier)
else {
return NSItemProvider()
}
return NSItemProvider(object: url as NSURL)
} preview: {
Text(apps.first == nil ? "no app" : apps.first!.bundleIdentifier)
Image(nsImage: apps.first == nil ? NSApp.applicationIconImage! : apps.first!.icon)
}
Button("next") {
apps.removeFirst()
}
.disabled(apps.isEmpty)
}
.frame(width: 200, height: 200)
.padding()
}
}
我做错了什么吗?这可能是一个(另一个)SwiftUI 错误吗?如果 preview
实际上是静态的并且只在第一次拖动时呈现,我该如何更改代码以便获得当前 Image
的 preview
?
谢谢。
我在@Asperi 的评论中的某处读到拖动预览仅在初始化时创建一次。因此,如果您向图像添加 .id,它会强制重绘并重新初始化预览:
Image(nsImage: apps.first == nil ? NSApp.applicationIconImage! : apps.first!.icon)
.id(apps.first?.bundleIdentifier) // here
.onDrag { ...
我在 Image
上有一个 .onDrag
。无论我是否自己提供 preview
,preview
总是卡在显示第一次拖动时出现的 Image
。 NSItemProvider
本身运行良好,我访问了正确的数据,但不在 preview
.
一个简单的例子(此处提供代码:https://github.com/godbout/DragPreview)
import SwiftUI
struct AppDetail {
let bundleIdentifier: String
let icon: NSImage
init(bundleIdentifier: String) {
self.bundleIdentifier = bundleIdentifier
if
let url = NSWorkspace.shared.urlForApplication(withBundleIdentifier: bundleIdentifier),
let representation = NSWorkspace.shared.icon(forFile: url.path).bestRepresentation(for: NSRect(x: 0, y: 0, width: 64, height: 64), context: nil, hints: nil)
{
self.icon = NSImage(size: representation.size)
self.icon.addRepresentation(representation)
} else {
self.icon = NSApp.applicationIconImage!
}
}
}
struct ContentView: View {
@State private var apps: [AppDetail] = [
AppDetail(bundleIdentifier: "com.apple.Mail"),
AppDetail(bundleIdentifier: "com.apple.MobileSMS"),
AppDetail(bundleIdentifier: "com.apple.Safari"),
]
var body: some View {
VStack(alignment: .center) {
Image(nsImage: apps.first == nil ? NSApp.applicationIconImage! : apps.first!.icon)
.onDrag {
guard
let app = apps.first,
let url = NSWorkspace.shared.urlForApplication(withBundleIdentifier: app.bundleIdentifier)
else {
return NSItemProvider()
}
return NSItemProvider(object: url as NSURL)
} preview: {
Text(apps.first == nil ? "no app" : apps.first!.bundleIdentifier)
Image(nsImage: apps.first == nil ? NSApp.applicationIconImage! : apps.first!.icon)
}
Button("next") {
apps.removeFirst()
}
.disabled(apps.isEmpty)
}
.frame(width: 200, height: 200)
.padding()
}
}
我做错了什么吗?这可能是一个(另一个)SwiftUI 错误吗?如果 preview
实际上是静态的并且只在第一次拖动时呈现,我该如何更改代码以便获得当前 Image
的 preview
?
谢谢。
我在@Asperi 的评论中的某处读到拖动预览仅在初始化时创建一次。因此,如果您向图像添加 .id,它会强制重绘并重新初始化预览:
Image(nsImage: apps.first == nil ? NSApp.applicationIconImage! : apps.first!.icon)
.id(apps.first?.bundleIdentifier) // here
.onDrag { ...