0

Update: This code works in the simulator, but not on my device. Obviously, I'm needing it to work on both.

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
    }
3
  • @Jay any ideas? Commented Mar 1, 2022 at 3:00
  • 1
    stackoverflow.com/a/64018573/341994 Commented Mar 1, 2022 at 3:24
  • @matt, thanks for your speedy reply. Would you be willing to post an answer showing me how I could implement the things mentioned at the link above? I don't mean to be an inconvenience, I'm just new and don't understand. Also, update: I tried my current project on a simulator, instead of my physical device, and it works. I'm not sure why it works for a simulator but not my device. Commented Mar 1, 2022 at 3:40

1 Answer 1

0

Thanks to matt, who commented above, I was able to find out that it's a security issue. Adding this simple code resolved the issue:

let shouldStopAccessing = pickedFolderURL.startAccessingSecurityScopedResource()
        defer {
          if shouldStopAccessing {
            pickedFolderURL.stopAccessingSecurityScopedResource()
          }
       }

I added it right before this line of code that can be seen above:

let text = createStringFromSelectedFile(fileURL: myURL)

I got this code from here: StackOverflow Post

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.