'Drag and drop with custom type identifier doesn't work
I'm trying to achieve drag and drop on macOS with a custom type identifier to avoid collisions but it doesn't seem to work. First, here's a working example with a public and known identifier:
struct ReleaseView: View {
let id: Int
var body: some View {
GeometryReader { _ in
VStack(spacing: 16) {
Image(nsImage: NSImage(named: NSImage.networkName)!)
.contentShape(Rectangle())
.onDrag {
return NSItemProvider(item: "\(self.id)" as NSString, typeIdentifier: NSPasteboard.PasteboardType.string.rawValue)
}
DropZone()
}
}
}
}
struct DropZone: View {
@State var isDragging = false
var body: some View {
RoundedRectangle(cornerRadius: 16)
.stroke(style: StrokeStyle(lineWidth: 4, dash: [8, 8]))
.background(isDragging ? Color.secondary : Color.clear)
.frame(width: 100, height: 100)
.onDrop(of: [NSPasteboard.PasteboardType.string.rawValue], isTargeted: self.$isDragging) { itemProvider in
print(itemProvider)
return true
}
}
}
In this example, you can drag the image above into the drop zone and it will print out the provider. Now, merely changing the typeIdentifier
breaks everything.
static let sharedTypeIdentifier = "com.procrastin8.plzwork"
struct ReleaseView: View {
// skipping the unchanged bits
.onDrag {
return NSItemProvider(item: "\(self.id)" as NSString, typeIdentifier: sharedTypeIdentifier)
}
}
struct DropZone: View {
// skipping the unchanged bits
.onDrop(of: [sharedTypeIdentifier], isTargeted: self.$isDragging) { itemProvider in
print(itemProvider)
return true
}
}
Now this doesn't work. Using the same constant here, so it's not a string mismatch. Just yet another SwiftUI bug?
Solution 1:[1]
The typeIdentifier
in above is not just a unique string, it must be UTI.
If you want to use some custom-application-specifc UTI (think twice if you really need it), then you have to register one according to Apple rules, starting from
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeIdentifier</key>
<string>com.procrastin8.plzwork</string>
...
in app Info.plist
See details specifically in Declaring New Uniform Type Identifiers
And wide collection in Technical Q&A QA1796
Solution 2:[2]
Nowadays, you can add a type identifier through target project and it adds the UTI string automatically on the Info.plist, as explained on this Raywenderlich article.
Walkthrough
- Select the project on Project Navigator
- Select the project target under "Targets" section
- Select the "Info" tab
- Expand "Exported Type Identifiers"
- Click + to add a new UTI
- Enter a description for the Description field
- Enter your identifier for the Identifier field with the same value you used in your code
- Under Conforms To enter public.data
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Mushu |