How to Read Data from Text File iOS 15

I've followed the tutorials, yet I cannot seem to get this feature to work. When the user selects the barButtonItem, DocumentPicker opens allowing the user to select a .txt file. I then take the URL to the selected file and attempt to return a string from it; however, I'm getting the following error: "The file “Test.txt” couldn’t be opened because you don’t have permission to view it." What am I missing? Did I fail to ask for permission somewhere? I've tried cleaning the build folder - didn't work.

@IBAction func importFileBtnTapped(_ sender: Any) {
        selectFiles()
    }
    
    
    func selectFiles() {
        let types = UTType.types(tag: "txt",
                                 tagClass: UTTagClass.filenameExtension,
                                 conformingTo: nil)
        let documentPickerController = UIDocumentPickerViewController(forOpeningContentTypes: types)
        documentPickerController.delegate = self
        self.present(documentPickerController, animated: true, completion: nil)
    }
    
    
    func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
        guard let myURL = urls.first else {
            let alert = SCLAlertView()
            alert.showError("ERROR", subTitle: "Unable to retrieve document.")
            return
        }
        let text = createStringFromSelectedFile(fileURL: myURL)
        if text == "error" {
            print("ERROR creating a string from the selected file.")
            return
        }
        let separatedStrings = decipherString(text: text)
        if separatedStrings.first == "error" {
            print("ERROR deciphering the string in ClaimInfoViewController")
            return
        }
        for string in separatedStrings {
            print("\(string)")
        }
        print("import result: \(myURL)")
    }
    
    
    func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
        dismiss(animated: true, completion: nil)
    }
    
    
    func createStringFromSelectedFile(fileURL: URL) -> String {
        var text = String()
        do {
            text = try String(contentsOf: fileURL)
        }
        catch {
            print("ERROR in the createStringFromSelectedFile function in ClaimInfoViewController")
            print("The error: \(error.localizedDescription)")
            let alert = SCLAlertView()
            alert.showError("ERROR", subTitle: "Unable to read the file. Please try again.")
            return "error"
        }
        return text
    }
    
    func decipherString(text: String) -> [String]{
        let newText = text
        let startIndexes = ["<Claim#",
                            "<File#",
                            "<DateOfLoss:"
        ]
        var claimNumber = String()
        var fileNumber = String()
        var dateOfLoss = String()
        
        for indexValue in startIndexes {
            guard let index = newText.firstIndex(of: ">") else { return ["error"] }
            let newString = String(newText[..<index])
            
            if indexValue == "<Claim#" {
                claimNumber = newString
            }
            else if indexValue == "<File#" {
                fileNumber = newString
            }
            else if indexValue == "<DateOfLoss:" {
                dateOfLoss = newString
            }
        }
        
        let finalText = [claimNumber, fileNumber, dateOfLoss]
        
        return finalText
    }

You have to use very specific methods for reading the contents of these files because they are outside of your app's sandbox. Normally, for security reasons, your app cannot read or write to any file on the file system. Hopefully, you can understand why these restrictions are in place: You wouldn't want any app you download to have full access to your file system.

The "Working with External Documents" section of the documentation contains a discussion of this point. Read it carefully.

This article, although specifically about directories, may be helpful as well.

1 Like