SwiftUI onDrag not showing preview image when running on device

I noticed an issue with the drag and drop features in SwiftUI that are available since iOS 13.4. The drag and drop operation with the .onDrag and .onDrop modifiers works fine in the simulator, but on a real device (iPhone and iPad) you just see a transparent rect, instead of the view while dragging the view.
Does anyone have a solution to get the correct preview image while the view is dragged?

Code Block
struct MainView: View {
@State var isDropTarget = false
var body: some View {
VStack{
Image(systemName: "doc.text")
.font(.system(size: 40))
.frame(width: 150, height: 150)
.onDrag { return NSItemProvider(object: "TestString" as NSString) }
Color.orange
.opacity(isDropTarget ? 0.5 : 1)
.onDrop(of: ["public.text"], isTargeted: $isDropTarget) { items in
for item in items {
if item.canLoadObject(ofClass: NSString.self) {
item.loadObject(ofClass: String.self) { str, _ in
print(str ?? "nil")
}
}
}
return true
}
}
}









Accepted Reply

Well, it seems like this issue is fixed with iOS 14. Tested it with the iOS 14 beta 4 and now the preview image is displayed correctly while dragging.

Replies

I've been struggling with drag and drop as a beginner. Why does your snippet above produce a warning Result of call to loadObject(ofClass:completionhandler:) is unused? And why would the result print, but when used to update a variable in view produce an error about immutable self?



Code Block swift
import SwiftUI
struct DragNDrop: View {
@State var isDropTarget = false
var displayThisNumber: Int = 0
var body: some View {
VStack{
Text(String(displayThisNumber))
ZStack {
Image(systemName: "5.circle.fill")
Circle()
}
.font(.system(size: 40))
.onDrag { return NSItemProvider(object: String(Int(5)) as NSString) }
Color.orange
.opacity(isDropTarget ? 0.5 : 1)
.onDrop(of: ["public.text"], isTargeted: $isDropTarget) { items in
for item in items {
if item.canLoadObject(ofClass: NSString.self) {
item.loadObject(ofClass: String.self) { str, _ in
guard str != nil else { return }
displayThisNumber += Int(str)
}
}
return true
}
}
}
}
}

Thanks for your comment. The loadObject function of the NSItemProvider returns a Progress element which you can use to display a progress to the user while the item is loaded. I skipped that in this example.
Your code crashes, because you need to declare your variable as a @State var, when the variable affects swiftui code and you want to change it in runtime.

Coming back to my initial question, do you also have the issue, that you see the image if you drag running the simulator, but when running on a real device, you only see a transparent rect as preview image?

Also struggling with Drag-n-Drop in SwiftUI within an app. If you find an answer to this, please post it. I'll be posting other related questions about my specific issue.
Well, it seems like this issue is fixed with iOS 14. Tested it with the iOS 14 beta 4 and now the preview image is displayed correctly while dragging.