I'm having an .onDrag
on an Image
. Whether I provide a preview
myself or not, the preview
always gets stuck to show the Image
that appeared on the first drag. The NSItemProvider
itself works well and I access the proper data, but not within the preview
.
A simple example (code available here: 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()
}
}
Anything I'm doing wrong? Could this be a(nother) SwiftUI bug? If the preview
is actually static and only rendered at the first drag, how could I change the code so that I get the preview
of my current Image
?
Thanks.
CodePudding user response:
I read somewhere in a comment by @Asperi that the drag preview is only created once at init. So if you add an .id to the image it forces a redraw and reinit of preview:
Image(nsImage: apps.first == nil ? NSApp.applicationIconImage! : apps.first!.icon)
.id(apps.first?.bundleIdentifier) // here
.onDrag { ...