This example is based on the latest version of Swift 6.2 for macOS.
I have several classes that cannot conform to Codable for various reasons. This, unfortunately, prevents me from using Transferable. If I serialize a class instance into a Data blob and use that for drag-and-drop, it works perfectly — the drag operation succeeds. However, the destination has no way to distinguish between different types of Data blobs.
All I’d need is a way to specify a unique identifier and type that I could reference in the drop handler to determine what kind of object I’m working with.
Being restricted to Transferable feels quite limiting when your data models can’t conform to Codable. It’s honestly frustrating. Has anyone else run into this issue? Is there a reliable workaround?
I tried creating a Transferable wrapper like this:
struct CustomObjectTransfer: Codable, Transferable
{
var data: Data
static var transferRepresentation: some TransferRepresentation
{
// Cannot use '.myGreatSettings' because Main actor–isolated static property 'myGreatSettings' cannot be referenced from a nonisolated context
CodableRepresentation(contentType: .init(exportedAs: "com.yourProject.settings"))
}
}
extension UTType
{
static let myGreatSettings: UTType = UTType("com.yourProject.settings")!
}
In my list view
.draggable ( CustomObjectTransfer(data: myObjectData) )
The UI correctly recognizes the item as draggable. If I misspell the exportedAs identifier, it even throws an error, confirming that the exported type is being recognized by the system.
However, the drop destination completely ignores this type:
.dropDestination(for: CustomObjectTransfer.self)
{ items, location in
dump(items)
return true
}isTargeted:
{ isTargeted in
myDestinationIsTargeted = isTargeted
}
If I switch to using Data.self directly — wrapping the original object data manually — everything works. I can deserialize and validate the data as needed.
The problem arises when handling multiple custom drag types. The drop target accepts any data, regardless of its intended type. You only find out the actual type after the drop occurs, during validation — which is too late. By then, isTargeted has already turned true, making the drop appear valid to the user when it actually isn’t.
Again anyone else feel this pain? Or is there a workaround that I am missing?