I was also looking for a workaround, but I think I actually came up with a workable solution. I took a completely different approach by not trying to drag and drop the PersistentModel
objects themselves, but instead, dragging and dropping the PersistentIdentifier
struct from a PersistentModel
object. This works well because PersistentIdentifier
is already Codable
and it is very easy to make it Transferable.
Also, a PersistentIdentifier
struct can be used to retrieve its corresponding PersistentModel
object from the ModelContext.
I have published a complete working sample program demonstrating this on GitHub: https://github.com/Whiffer/SwiftDataDragAndDropExample
The important concepts are:
- Extend
PersistentIdentifier
to be Transferable
and define your own contentType
for it
extension PersistentIdentifier: Transferable {
public static var transferRepresentation: some TransferRepresentation {
CodableRepresentation(contentType: .persistentModelID)
}
}
- Extend
PersistentIdentifier
with a generic convenience function to retrieve PersistentModel
objects from the ModelContext
extension PersistentIdentifier {
public func persistentModel<Model>(from context: ModelContext) -> Model? where Model : PersistentModel {
return context.model(for: self) as? Model
}
}
- Use
PersistentIdentifier
structs with the .draggable() and .dropDestination() View Modifiers
Text(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard))
.draggable(item.persistentModelID)
.dropDestination(for: PersistentIdentifier.self) { persistentModelIDs, _ in
let targetItem = item // for clarification
for persistentModelID in persistentModelIDs {
if let draggedItem: Item = persistentModelID.persistentModel(from: self.modelContext) {
print("\(draggedItem.timestamp) dropped on: \(targetItem.timestamp)")
}
}
return true
}