How to get the filename of dropped file in SwiftUI?
Asked Answered
E

2

9

I have been trying to find out how to get the filename of an image dropped into a SwiftUI View.

The code fragment is as follows:

struct MainView: View, DropDelegate {

  @ObservedObject var userState : UserState

  var body : some View {
    Group {
      if (self.userState.editing) {
        BlackoutView()
      } else {
        DropView()
      }
    }
    .frame(minWidth: 320, idealWidth: 640, maxWidth: .infinity, minHeight: 240, idealHeight: 480, maxHeight: .infinity, alignment: .center)
    .onDrop(of: [(kUTTypeImage as String), "public.pdf"], delegate: self)
  }

  func dropUpdated(info: DropInfo) -> DropProposal? {
    let proposal = DropProposal.init(operation: .copy)
    return proposal
  }

  func performDrop(info: DropInfo) -> Bool {
    print("perform drop")
    userState.editing = true
    return true
  }

}

When I drop an image onto the app, it runs performDrop. How can one obtain the filename of the image dropped onto the app?

It runs on macOS.

Engelbert answered 27/10, 2019 at 14:52 Comment(0)
M
19

Having spent more than an hour struggling with the apis (the documentation is almost nonexistent), here is what worked for me:

// The onDrop registration
.onDrop(of: [(kUTTypeFileURL as String)], delegate: self)

...

func performDrop(info: DropInfo) -> Bool {

    guard let itemProvider = info.itemProviders(for: [(kUTTypeFileURL as String)]).first else { return false }

    itemProvider.loadItem(forTypeIdentifier: (kUTTypeFileURL as String), options: nil) {item, error in
        guard let data = item as? Data, let url = URL(dataRepresentation: data, relativeTo: nil) else { return }
        // Do something with the file url
        // remember to dispatch on main in case of a @State change
    }

    return true
}

Please note that I have omitted any validation, so this code grabs the first url from any dropped files

Midmost answered 28/10, 2019 at 0:28 Comment(0)
R
0

Here is my drop files demo:

import SwiftUI
import UniformTypeIdentifiers

struct ContentView : View {
    
    @State private var dropFilesHere = Image(systemName: "leaf")

    var body: some View {
        VStack {
            self.dropFilesHere
                .resizable()
                .scaledToFit()
                .frame(width: 150, height: 150)
                .onDrop(of: [.item], isTargeted: nil, perform: {
                    providers, _ in
                    
                    providers.forEach { provider in
                        provider.loadFileRepresentation(forTypeIdentifier: UTType.item.identifier) { url, error in
                            if let url = url {
                                print(url)
                            }
                        }
                    }
                    return true
                })
            Text("Drop image here")
        }
    }
}
#Preview {
    ContentView()
}
Recti answered 2/5, 2024 at 18:33 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.