Search code examples
iosswiftxcodeswiftuiswiftui-fileimporter

SwiftUI `fileImporter` ViewModifier not working on iOS 15


I'm seeing some weird behaviour with the fileImporter modifier on my iOS app. When running this View code on an iPhone running iOS >= 16, it runs fine, the document picker presents itself and passes back the result, no issues.

struct SomeView: View {
    @State private var importingFile = false

    var body: some View {
        List {
            Section(header: Text("Header"), footer: Text("Footer") {
                if let uploadTitle = viewModel.uploadTitle {
                    Text("Tap to open")
                    .onTapGesture {
                        importingFile = true
                    }.fileImporter(isPresented: $importingFile, allowedContentTypes: [.pdf]) { result in
                        didImportFile(withResult: result)
                    }
                }
            }
        }
    }

    func didImportFile(withResult result: Result<URL, Error>) {
        print("Do something with result")
    }
}

The problem occurs when running on iOS 15 (possibly 14, unable to test atm), wherein, nothing happens at all. No document picker is presented.

Looking at the official documentation here, this API is marked as iOS 14 compatible and I'm definitely not adding an #if available checks so I know it's not an api compatibility issue.

I've also searched on OpenRadar and can't find a mention of the fileimporter modifier anywhere either.

Hoping one of the many geniuses here can point me in the right direction and possibly help me out with what I'm doing wrong? Appreciate any help anyone can offer.


Solution

  • I had this exact problem. Moving the fileImporter modifier outside of my enclosing Form worked for me in iOS 15. The equivalent in your example would be:

    struct SomeView: View {
        @State private var showingFilePicker = false
    
        var body: some View {
            List {
                Section(header: Text("Header"), footer: Text("Footer") {
                    if let uploadTitle = viewModel.uploadTitle {
                        Button("Tap to open") {
                            showingFilePicker = true
                        }
                    }
                }
            }.fileImporter(isPresented: $showingFilePicker, allowedContentTypes: [.pdf]) { result in
                didImportFile(withResult: result)
            }
        }
    
        func didImportFile(withResult result: Result<URL, Error>) {
            print("Do something with result")
        }
    }