.dropDestination doesn't execute with my custom transferable type
Asked Answered
A

4

5

I have defined

import SwiftUI
import UniformTypeIdentifiers

enum LayerType: String, Codable, RawRepresentable {
    case text
    case image
}

struct TransferableLayer: Identifiable, Hashable, Codable, Transferable {
    var id: UUID
    var type: LayerType
    
    init(id: UUID, type: LayerType) {
        self.id = id
        self.type = type
    }

    static var transferRepresentation: some TransferRepresentation {
        CodableRepresentation(contentType: .transferableLayer)
    }
}

extension UTType {
    static let transferableLayer = UTType(exportedAs: "co.customUTType.transferableLayer")
}

Note: I've added it in Exported Type Identifiers as well: enter image description here

Also I have LayersView where I assign .draggable attribute to Text:

 ForEach(Array(textLayers.enumerated()), id: \.element.id) { index, textLayer in
                    ...
                        Text(textLayer.text)
                           .draggable(TransferableLayer(id: textLayer.id, type: LayerType.text))
...
}

and I have PanelView where I added

.dropDestination(for: TransferableLayer.self) { droppedLayers, location in
   print("I'm inside dropDestination")
}

and print() code inside dropDestination doesn't call when I drag'n'drop my textLayer on Panel. But it shows preview properly and I see changes which I've made there.

UPD:

I've searched for similar question/answers on SO and found this one: Drag&Drop Custom Types with Transferable Protocol in Swiftui for macOS

Seems issue to Transferable protocol and how it works with Custom types on MacOS. BTW it works on Supported Destination as Mac Catalyst

Autotomy answered 15/12, 2023 at 23:0 Comment(3)
What's the purpose of .position(textLayer.position)? Does it work if you remove that?Concordant
@Concordant I've updated my question. Actually .position(textLayer.position) is not related to this question. It doesn't work if I remove it as well.Autotomy
I tried this (and my own implementation based on 'Meet Transferable'/ serialcoder.dev/text-tutorials/swiftui/…) and have the same problem, regardless of whether I use public.content public.data, public.text, or public.json (which is what Apple recommends in developer.apple.com/documentation/uniformtypeidentifiers/…)Lamed
S
3

CodableRepresentation is JSON, which is text.

You are using an Exported Type Identifier that conforms to com.public.data.

Use public.text instead.

Semiramis answered 7/3 at 14:21 Comment(0)
A
2

Rather than using com.public.data try using public.data. Remove com string from conformsTo field, weirdly when identifier is added with com it doesn't work on MacOS.

Refer this video from apple: https://developer.apple.com/videos/play/tech-talks/10696

Asclepius answered 19/5 at 7:37 Comment(1)
Randomly, I had the same issue and have been smashing my head against my keyboard. This was the issue. Thank you!Muskogean
R
1

This seems to be some sort of namespace problem. A little late for the OP, but in case anyone else has the same issue, it seems you can't have the last part of the identifier of the Exported Type Identifier named the same as a struct or class in the project, regardless of case.

For example, in the question above, the existence of the struct TransferableLayer means that the identifier on the Exported Type Identifier (and corresponding exportedAs setting on the UTType) can't be co.customUTType.transferableLayer as ".transferableLayer" clashes with the TransferableLayer struct.

From my experience, renaming it to co.customUTType.transferable-layer should resolve the issue and get dragging and dropping working as expected.

Ribbonfish answered 28/7 at 15:34 Comment(1)
Just don't use underscores (I haven't had a namespace problem, but wanted to try this to eliminate it as the source of my drop target not working). Underscore = crash.Lamed
L
1

The clue lay in https://developer.apple.com/documentation/uniformtypeidentifiers/defining-file-and-data-types-for-your-app which gives a sample of the plist entry. Plists are still automatically generated, but no longer show up in the file list in Xcode 16, so you have to open it from the finder.

You'll automatically get an entry (with human-readable labels instead of the keys in the example), and I constructed mine manually, but I managed to get your example working by simply deleting the 'icons' entry that was automatically created in the plist.

Ed. to add

This is so erratic that I cannot even file a bug report. Constructing the info.plist entry manually from the document linked above works every time. Sometimes, adding an exportedTypeIdentifier in the target/info section works. Sometimes you even get the info.plist exposed in the list of files (though not very often). Sometimes deleting the 'icons' entry works, sometimes it doesn't. If you create new files in a new project and paste the content of existing files, they tend to work the same as the original project. If you copy them from the previous project, they may or may not work (so previously working targets fail, and previously not-working targets succeed).

Whether dropping works or not seems to be consistent between launches of the app and launches of Xcode (have not yet tested restarting my computer, but I'm hopeful).

Five variants of the same app with the same content, in various combinations of pasting/importing and working/not-working, and I've given up on trying to file a radar.

I will now implement Drag and Drop in my app, do whatever I fiddling with the info.plist I need to do to get it to work, and report back on whether it remains stable.

plist settings (Exported type identifiers/UTExportedTypeDeclarations)

Lamed answered 23/9 at 0:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.