skip to Main Content

I am using the .fileImporter modifier in SwiftUI to import pdf files in my app. I’m having a few issues. Firstly the data is slow to load and often it doesn’t load and gives message Internal Error Couldn’t communicate with a helper application.

But the main issue is if the modal view is dismissed with a swipe down, it cannot be presented again. Presumably because the binding $showFileImporter is not reset. If the cancel button is pressed to dismiss it works fine. I don’t know if there is anyway to force it to fullScreen to get around this.

Here is my code:

.fileImporter(isPresented: $showFileImporter, allowedContentTypes: [.pdf]) { result in
        switch result {
        case .success(let url):
            url.startAccessingSecurityScopedResource()
            if let pDFDocument = PDFDocument(url: url) {
                if let data = pDFDocument.dataRepresentation() {
                    // handle data
                    
                }
            }
        case .failure(let error):
            print(error)
        }
    }

2

Answers


  1. I can confirm my .fileImporter also does not reset the isPresented binding on swipe-down. One way to be for certain is to change your button that presents the file importer from $showFileImporter = true to $showFileImporter.toggle(). On swiping to dismiss the file importer, you have to press the button twice to present again.

    Unfortunately this seems to be yet another half-baked SwiftUI thing, but I did find a suitable work-around – handling this case with the presenting button itself:

    Button(action: {
    if showFileImporter {
        // NOTE: Fixes broken fileimporter sheet not resetting on swipedown
        showFileImporter = false
        DispatchQueue.main.asyncAfter(deadline: .now()+0.2, execute: {
            showFileImporter = true
        })
    } else {
        showFileImporter = true
    }
    }, label: { ... })
    

    I tried just calling .toggle() twice in a row sequentially but needed a slight delay for the trigger to register.

    Edit:
    I also noticed you didn’t call url.stopAccessingSecurityScopedResource(), which you should do after calling to your pDFDocument.

    Login or Signup to reply.
  2. The issue persists as of August 2022. I needed to implement Joseph Dvorak’s most excellent fix in multiple places so abstracted it on to any equatable binding:

    // Usage
    $showFileImporter.trampolineIfNeeded(to: true)
    
    
    // Implementation
    extension Binding where Value: Equatable {
        func trampolineIfNeeded(to: Value, via: Value) {
            if wrappedValue == to {
                wrappedValue = via
                DispatchQueue.main.asyncAfter(deadline: .now()+0.2, execute: {
                    wrappedValue = to
                })
            } else {
                wrappedValue = to
            }
        }
    }
    
    extension Binding where Value == Bool {
        func trampolineIfNeeded(to: Value) {
            trampolineIfNeeded(to: to, via: !to)
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search