4

I'm trying to implement a simple drag and drop with NSString. I can get this working with NSURL but not NSString. Every time I try the drag and drop I always end up with a nil value. Here is my code:

struct ContentView: View 
{

    var body: some View 
    {
        Text("Hello World")
            .onDrag { NSItemProvider(object: "Hello World" as NSString) }
    }
}

Then the dropped object:

struct DroppedView: View, DropDelegate
{
    var body: some View 
    {
        Text("Drop here")
            .onDrop(of: ["public.text"], delegate: self)
    }

    func performDrop(info: DropInfo) -> Bool
    {
         if let items = info.itemProviders(for: ["public.text"]).first
         {
             item.loadItem(forTypeIdentifier: "public.text", options: nil)
             {
                 (data, error) in
                
                 print(data)
             }
         }
         return true
    }
}

I would have expected the output to be "Hello World". What am I missing?

iphaaw
  • 6,764
  • 11
  • 58
  • 83

1 Answers1

11

I don't recall where (somewhere in depth of Apple's docs) but I met occasionally that we should not use base UTTypes (like public.text) for data loading - instead only concrete types (like in this answer) must be used.

The NSString register itself as UTF-8 plain text type provider (it conforms to public.text but cannot be decoded to), so worked variant is

func performDrop(info: DropInfo) -> Bool
{
    if let item = info.itemProviders(for: ["public.utf8-plain-text"]).first
    {
        item.loadItem(forTypeIdentifier: "public.utf8-plain-text", options: nil)
        {
            (data, error) in
            if let data = data as? Data {
                print(NSString(data: data, encoding: 4) ?? "failed")
            }
        }
    }
    return true
}

Tested with Xcode 13 / macOS 11.5.2

demo

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Asperi
  • 228,894
  • 20
  • 464
  • 690
  • Well, actually it is not a bug - I don't recall where (somewhere in depth of Apple's docs) but I met occasionally that we should not use *base* UTTypes (like *public.text*) for data loading - instead only concrete types (like in this answer) must be used. – Asperi Nov 19 '21 at 19:20