I have reviewed some questions on Stack Overflow about drag and drop reorder with SwiftUI, and this one was particularly helpful: SwiftUI | Using onDrag and onDrop to reorder Items within one single LazyGrid?
I'm looking to expand this functionality where I drag something from one list of items to another in my SwifUI app. Let's say I have a Task list:
//TaskView.swift
ScrollView{
VStack{
ForEach(model.tasks, id: \.self){ task in
Text(task.name)
.onDrag{
NSItemProvider(object: String(task.id) as NSString)
}
}
}
}
...and I also have a Project list that I can drag a Task onto to move it to that project:
//ProjectView.swift
ScrollView{
VStack{
ForEach(model.projects, id: \.self){ project in
Text(project.name)
.onDrop(of: [UTType.text], delegate: ProjectDropDelegate(project: project))
}
}
}
The part I'm struggling with is in my ProjectDropDelegate where I'm trying to determine a couple things:
- What kind of object is being dropped on me? (it must be a task)
- If it's a task, what is its
idso I can take action on it? (or, ideally, I'd get the wholeTaskobject to work with)
I can't figure out how to make my NSItemProvider in .onDrag use anything other than a string and still work with my SwiftUI drag/drop functionality. For what it's worth, my Task and Project objects are Core Data classes.
How can I make NSItemProvider contain key-value pairs so I can pass a type identifier string like myapp.task (for #1 above) and an id (for #2)?
After further investigation, I found a much simpler way to handle all this. I think
NSItemProvideris a bit of a red herring if all you need to do is move data from one part of your app to another. Here's how I went about it and it seems to work great.I alluded to
model.taskswhen I generated my list of tasks. Here's more about it:I added a
draggedTaskoptional to my model then I set it in myonDragmodifier like this:I just pass an empty
Stringobject toNSItemProviderto satisfy its requirement for dragging something. Then in myProjectDropDelegateI can have all the stuff I need, included setting a hovered UI state:This is much simpler than I was initially making it.