Drag and Drop Question

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?

Thanks for the post and apologies for the delay. I see the code, but can you produce something I can just download and run?

Do you get the same results with just the relevant code in a small test project? If so, please share a link to your test project. That'll help us better understand what's going on. If you're not familiar with preparing a test project, take a look at Creating a test project.

Albert Pascual
  Worldwide Developer Relations.

Thank you for the reply. I shared the test project to my apple support ticket that I created. The apple support ticket is Case-ID: 16525926.

Let me elaborate some more as to what I am referring too. In my app we are using polymorphism that cannot be Codable. But we need to drag and drop objects into a predefined box, label, table, etc and if we simply code everything as a data blob it works no problem. But the user will not know that the drop area for Character Names was not accepted if you dropped it on Played by drop zone.

The below "Standard Object" is shared by the other two classes. This gets ignored by Codable.

So, if you try and package them up without Codable in your own data blob, it's fine. But the drop zone cannot determine that the data blob from CharecterName is different from PlayedBy. Therefore accepts drop. You can use validation afterwards to prevent errors. But that is after the mouse pointer gives you a green + sign saying that this object belongs to this drop. Im trying to avoid this confusion on the UI.

class StandardObject
{
    var objectID : UInt32 = 0
    // standard functions and parameters shared by all objects
}
class CharecterName: StandardObject, Codable, Identifiable
{
    var firstName = ""
    var lastName = ""
    
    func getObjectData() -> Data
    {
        let encoder = JSONEncoder()
        return try! encoder.encode(self)
    }
}
class PlayedBy: StandardObject, Codable, Identifiable
{
    var firstName = ""
    var lastName = ""
    
    func getObjectData() -> Data
    {
        let encoder = JSONEncoder()
        return try! encoder.encode(self)
    }
}
Drag and Drop Question
 
 
Q