2

Am porting over my UIDocumentPickerViewController into SwiftUI and whether I pick a file or cancel the picker I keep getting the error:

[DocumentManager] The view service did terminate with error: Error Domain=_UIViewServiceErrorDomain Code=1 "(null)" UserInfo={Terminated=disconnect method}

I call the UIDocumentPickerViewController within my View with .sheet:

.sheet(isPresented: self.$isShowingDocumentPicker, content: {
   DocumentPickerView(isShowing: $isShowingDocumentPicker, xFile: $xFile)
})

Here is a the code included into a fully runnable sample:

    import SwiftUI
    import UniformTypeIdentifiers
    
    struct ContentView: View {
        @State var isShowingDocumentPicker = false
        @State var xFile = XFile()
        
        var body: some View {
            Button {
                isShowingDocumentPicker = true
            }
            label: {
                Text("Select File")
            }
            .sheet(isPresented: self.$isShowingDocumentPicker, content: {
                            DocumentPickerView(isShowing: $isShowingDocumentPicker, xFile: $xFile)
                            })
//even using .fileImporter below in place of .sheet still produces the same error

//.fileImporter(
//            isPresented: $isShowingDocumentPicker,
//            allowedContentTypes: [.spreadsheet, .commaSeparatedText]) { result in
//            switch result {
//            case .success(let file):
//                print(file.absoluteString)
//            case .failure(let error):
//                print(error.localizedDescription)
//            }
        }
        
    }
    
    struct XFile {
        var fileName    : String
        let supportedTypes: [UTType] = [.text]
        var fullPath    : String
        
        init () {
            fileName = "no file selected"
            fullPath = ""
        }
    }
    
    struct DocumentPickerView: UIViewControllerRepresentable {
        @Binding var isShowing: Bool
        @Binding var xFile: XFile
        
        func makeUIViewController(context: Context) -> some UIViewController {
            let pickerViewController = UIDocumentPickerViewController(forOpeningContentTypes: xFile.supportedTypes)
            pickerViewController.allowsMultipleSelection = false
            pickerViewController.shouldShowFileExtensions = false
            pickerViewController.delegate = context.coordinator
            return pickerViewController
        }
        
        func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
            print ("in updater")
        }
        
        func makeCoordinator() -> Coordinator {
            Coordinator(isShowing: $isShowing, xFile: $xFile)
        }
        
        class Coordinator: NSObject, UIDocumentPickerDelegate {
            @Binding var isShowing: Bool
            @Binding var xFile: XFile
            
            init(isShowing: Binding<Bool>, xFile: Binding<XFile>) {
                _isShowing = isShowing
                _xFile      = xFile
            }
            
            func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
                
                for url in urls {
                    guard url.startAccessingSecurityScopedResource() else {
                        print ("error")
                        return
                    }
                    
                    
                    if let fileAttributes = try? FileManager.default.attributesOfItem(atPath: url.path) {
                        if let bytes = fileAttributes[.size] as? Int64 {
                            if bytes > 2048000 {
                                print ("too big")
                            } else {
                                xFile.fullPath = url.absoluteString
                                xFile.fileName = url.lastPathComponent
                            }
                        }
                    }
                    do { url.stopAccessingSecurityScopedResource() }
                }
                print ("\(xFile.fileName)")
                controller.dismiss(animated: true)
                isShowing = false
            }
            
            func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
                print("Document picker was cancelled")
                //controller.dismiss(animated: false)
                // Dismiss the document picker
                isShowing = false
            }
        }
    }

This error occurs on both the simulator as well as my physical iPhone 13.

I've tried commenting out controller.dismiss, but that makes no difference.

Is this an error I can ignore? And if not, what am I missing?

  • Show a minimal reproducible code that produces your issue, see: [minimal code](https://stackoverflow.com/help/minimal-reproducible-example). Specifically, show the code of the view where you have your `.sheet(isPresented: ...)` and how you set the `xFile` – workingdog support Ukraine May 31 '23 at 03:01
  • 1
    @workingdogsupportUkraine Updated OP to include minimal code. – NewToSwiftUI May 31 '23 at 22:35

1 Answers1

0

Use [fileImporter][1] instead of trying to wrap UIDocumentPicker yourself. [1]: https://developer.apple.com/documentation/swiftui/form/fileimporter(ispresented:allowedcontenttypes:allowsmultipleselection:oncompletion:)?cmdf=fileImporter%20swiftui

Thomas Deniau
  • 2,488
  • 1
  • 15
  • 15