0

In my code the drag&drop function works fine with URL objects. But the exact same code for String objects does not. I have tried with countless casts and loadItem instead of loadObject ... no luck so far.

Can anyone help me here? It would be very much appreciated.

code for URL objects – Working

.onDrag {
    return NSItemProvider(object: item.url as NSURL) 
}

.onDrop(of: [UTType.url], isTargeted: $isDropping) { providers in
    _ = providers.first?.loadObject(ofClass: URL.self) { url, error in
        if let error = error { print(error.localizedDescription) }
        if let url = url {
            DispatchQueue.main.async {
                self.array2.insert(Item(title: "new", url: url), at: 0)
            }
        }
    }
    return true
}

the same with String does not:

.onDrag {
    return NSItemProvider(object: item.title as NSString) 
}

.onDrop(of: [UTType.text], isTargeted: $isDropping) { providers in
    _ = providers.first?.loadObject(ofClass: String.self) { string, error in
        if let error = error { print(error.localizedDescription) }
        if let string = string {
            DispatchQueue.main.async {
                self.array2.insert(Item(title: string, url: URL(string: "http://www.apple.com")!), at: 0)
            }
        }
    }
    return true
}

full MRE code:

import SwiftUI
import UniformTypeIdentifiers

struct Item: Identifiable {
    let id = UUID()
    var title: String
    var url: URL
}

struct ContentView: View {
    
    @State var array1: [Item] = [
        Item(title: "One", url: URL(string: "http://www.amazon.com")!),
        Item(title: "Two", url: URL(string: "http://www.apple.com")!),
        Item(title: "Three", url: URL(string: "http://www.example.com")!),
    ]
    @State var array2: [Item] = []
    @State var isDropping = false
    
    var body: some View {
        
        HStack(alignment: .top) {
            
            VStack(alignment: .leading) {
                ForEach(array1) { item in
                    Text(item.title)
                    Text(item.url.absoluteString).foregroundColor(.secondary)
                    
                        // DRAG
                        .onDrag {
                            return NSItemProvider(object: item.url as NSURL) // WORKS
                         // return NSItemProvider(object: item.title as NSString) // DOES NOT WORK
                        }
                }
            }
            .frame(maxWidth: .infinity)
            
            Divider()
            
            VStack(alignment: .leading) {
                ForEach(array2) { item in
                    Text(item.title)
                    Text(item.url.absoluteString).foregroundColor(.secondary)
                    
                }
            }
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .background(isDropping ? .green : .gray)
            
            
            // DROP with url/NSURL -- WORKS
            .onDrop(of: [UTType.url], isTargeted: $isDropping) { providers in
                
                _ = providers.first?.loadObject(ofClass: URL.self) { url, error in
                    if let error = error { print(error.localizedDescription) }
                    if let url = url {
                        DispatchQueue.main.async {
                            self.array2.insert(Item(title: "new", url: url), at: 0)
                        }
                    }
                }
                return true
            }

            // DROP with text/NSString -- DOES NOT WORK
            .onDrop(of: [UTType.text], isTargeted: $isDropping) { providers in
                
                _ = providers.first?.loadObject(ofClass: String.self) { string, error in
                    if let error = error { print(error.localizedDescription) }
                    if let string = string {
                        DispatchQueue.main.async {
                            self.array2.insert(Item(title: string, url: URL(string: "http://www.apple.com")!), at: 0)
                        }
                    }
                }
                return true
            }
        }
    }
}
ChrisR
  • 9,523
  • 1
  • 8
  • 26
  • ok, found the answer: https://stackoverflow.com/questions/69324953/swiftui-not-getting-dropped-nsstring-value-in-dropdelegate/69325742#69325742 – ChrisR May 08 '22 at 21:29

1 Answers1

0

As always thanks to @Asperi and his answer here:
SwiftUI: Not getting dropped NSString value in DropDelegate

This now works:

            .onDrop(of: [UTType.utf8PlainText], isTargeted: $isDropping) { providers in
                
                _ = providers.first?.loadItem(forTypeIdentifier: "public.utf8-plain-text") { data, error in
                    if let error = error { print(error.localizedDescription) }
                    if let data = data as? Data {
                        DispatchQueue.main.async {
                            let string = NSString(data: data, encoding: 4) ?? "failed"
                            print(string)
                            self.array2.insert(Item(title: string as String, url: URL(string: "http://www.apple.com")!), at: 0)
                        }
                    }
                }
                return true
            }
ChrisR
  • 9,523
  • 1
  • 8
  • 26