SwiftDataDragAndDropExample
No description available
Install / Use
/learn @Whiffer/SwiftDataDragAndDropExampleREADME
SwiftDataDragAndDropExample
*** NOTE: This project has evolved into a more complete solution for implementing drag and drop functionality with SwiftData PersistentModel objects in a SwiftUI App.
A new Swift Package to do this can be found at: https://github.com/Whiffer/swiftdata-transferrable.
The package implements generic extensions to the .draggable() and .dropDestination() SwiftUI View modifiers to faclilitate direct Drag and Drop operations with SwiftData PersistentModel objects.
A complete project that demonstrates how to use the package is available at: https://github.com/Whiffer/SampleSwiftDataTransferrable
==================================================================================
This project is one example of how to implement drag and drop functionality with SwiftData PersistentModel objects in a SwiftUI App. The primary issue that makes this difficult is that SwiftData PersistentModel objects are not Codable and they are not Transferable.
This solution takes a slightly 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.
Steps to Implement SwiftUI Drag and Drop with SwiftData objects
Make PersistentIdentifier conform to Transferable
Open your project settings, select the Info tab for your Target, then add a new Exported Type Identifier with the following properties:
Description: "SwiftData Persistent Model ID"
Identifier: "com.[your team].persistentModelID"
Conforms To: "public.data"
Create a UTType extension with your new Exported Type Identifier:
import UniformTypeIdentifiers
extension UTType {
static var persistentModelID: UTType { UTType(exportedAs: "com.[your team].persistentModelID") }
}
Finally, use the following code to create a PersistentIdentifier extension to make it Transferable:
extension PersistentIdentifier: Transferable {
public static var transferRepresentation: some TransferRepresentation {
CodableRepresentation(contentType: .persistentModelID)
}
}
Extend PersistentIdentifier with a generic convenience function
Create PersistentIdentifier extension to retrieve the SwiftData PersistentModel object for the given PersistentIdentifier
extension PersistentIdentifier {
public func persistentModel<Model>(from context: ModelContext) -> Model? where Model : PersistentModel {
return context.model(for: self) as? Model
}
}
Add .draggable() View modifiers
Supply the View modifier with the PersistentIdentifier from the PersistentModel object being dragged.
Text(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard))
.draggable(item.persistentModelID)
Add .dropDestination() View modifiers
Use the generic persistentModel() function from the PersistentIdentifier extension to retrieve the PersistentModel object being dragged
Text(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard))
.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
}
