Dejal
Dejal

Reputation: 873

SwiftUI receiving NSFilePromiseReceiver via NSItemProvider

I have a SwiftUI list that can receive dropped images. I want it to support file promises to get full-resolution images from the Photos app (on macOS, though presumably similar on iOS).

Here's a simplified edition of my code for the list and receiving a dropped image:

List {
    ForEach(blockManager.blockViewModels, id: \.id) { viewModel in
        Image(nsImage: viewModel.imageBlock.image)
            .resizable()
            .aspectRatio(contentMode: .fit)
            .frame(maxWidth: 1024)
    .onInsert(of: [.image, .fileURL, .text]) { index, itemProviders in
        for provider in itemProviders {
            if provider.canLoadObject(ofClass: NSImage.self) {
                _ = provider.loadObject(ofClass: URL.self) { url, error in
                    if let url, let image = NSImage(contentsOf: url)?.resized(width: preferredWidth) {
                        let block = ImageBlock(image: image, filename: url.lastPathComponent)
            
                        DispatchQueue.main.async {
                            // insert the image in the model data
                        }
                    }
                }
            }
        }
    }
}

But I can't figure out how to receive a file promise. I can detect a promise via this code:

func itemPromiseType(for provider: NSItemProvider) -> NSPasteboard.PasteboardType? {
    let types = NSFilePromiseReceiver.readableDraggedTypes.map { NSPasteboard.PasteboardType($0) }
    
    for type in types {
        if provider.hasItemConformingToTypeIdentifier(type.rawValue) {
            return type
        }
    }
    
    return nil
}

But my attempt to handle it doesn't work; the switch falls through to the default:

func createBlockWithPromise(from provider: NSItemProvider, type: NSPasteboard.PasteboardType, at dropIndex: Int) {
    provider.loadItem(forTypeIdentifier: type.rawValue) { [self] item, error in
        switch item {
            case let filePromiseReceiver as NSFilePromiseReceiver:
                filePromiseReceiver.receivePromisedFiles(atDestination: destinationURL, options: [:],
                                                         operationQueue: workQueue) { (fileURL, error) in
                    if let error = error {
                        print(error)
                    } else {
                        print(fileURL)
//                            self.handleFile(at: fileURL)
                    }
                }
            case let fileURL as URL:
                print(fileURL)
            default: break
        }
    }
}

The item:

(lldb) po item
▿ Optional<NSSecureCoding>
  ▿ some : <62706c69 73743030 d101025f 102f636f 6d2e6170 706c652e 70617374 65626f61 72642e70 726f6d69 7365642d 66696c65 2d636f6e 74656e74 2d747970 655b7075 626c6963 2e6a7065 67080b3d 00000000 00000101 00000000 00000003 00000000 00000000 00000000 00000049>

Any ideas? It feels like I'm close, just missing something obvious.

Upvotes: 2

Views: 145

Answers (0)

Related Questions