Read the files in that folder

Hi everyone,


My problem is that I want to read the files in that document folder. I use the code from this stackoverflow

https://stackoverflow.com/questions/31278869/file-access-in-a-sandboxed-osx-app-with-swift

+ the solution of the "Accessing applicationDocumentsDirectory"

https://forums.developer.apple.com/thread/84448


However, when I start my MacOS app (swift), I get only the URL.

print ("Restoring \(bookmark.key)")


How can I read all the files in this folder with the subfolders. Is there a working code example?


Thanks,

Replies

That may be a very partial answer which I hope will be relevant for your question.


My point was to be able to create a file in a sandboxed environment, XCode 8.3.


I did the following :


- call NSOpenPanel, just for selecting a directory where to authorize writing

- inside the completion handler of NSOpenPanel, call NSSavePanel to proceed with file creation.


And that finally worked.


Here is some code (I edited, so there may be some typos):


    @IBAction func newDossier(_ sender: NSMenuItem) {          // I answer to a menu selection

        let openPanel = NSOpenPanel()
        openPanel.message = "Choisir le dossier où enregistrer vos fichiers\n(Necassaire pour la gestion de la sécurité de l'ordinateur)"     // let user understand why we ask to select just a directory
        openPanel.prompt = "Choisir"
        openPanel.canChooseFiles = false
        openPanel.canChooseDirectories = true
        openPanel.canCreateDirectories = true
        openPanel.begin() {
            (result2) -> Void in
            if (result2 == NSFileHandlingPanelOKButton) {
   
                globalAllowedFolderUrl = openPanel.url!       // I save URL for later use
                storeBookmark(url: globalAllowedFolderUrl)
                Swift.print("allowedFolderUrl ", GlobalData.sharedGlobal.allowedFolderUrl)

                let savePanel = NSSavePanel()     // Now we proceed with savePanel
                savePanel.title = "Fichier de listes"
                savePanel.nameFieldStringValue = "default name"
                savePanel.prompt = "Créer"
                savePanel.allowedFileTypes = ["xxxx"]   // your file extension, if needed
                let fileManager = FileManager.default   
   
                savePanel.begin() { (result) -> Void in
                    if (result == NSFileHandlingPanelOKButton) {
                        let fileWithExtensionURL = savePanel.url!
                       globalDocURL=: fileWithExtensionURL  //  savePanel.URL! in a global
                       if fileManager.fileExists(atPath: fileWithExtensionURL.path) {   // file exists, warn user
                            let fileName = fileWithExtensionURL.deletingPathExtension().lastPathComponent
                            let folderName = fileWithExtensionURL.deletingLastPathComponent().lastPathComponent
                            self.errorExistingFile(fileName: fileName, folderName: folderName)
                        } else {     // We can create the file
                          
                            saveIFile()  // That's where we write data
                            saveBookmarks() // save the folder url; you know this func already
                        }
           
                    }       // result == NSModalResponseOK
                }       // beginWithCompletionHandler
   
            }
        }
    }



func saveFile()  {
      
    if globalAllowedFolderUrl == nil {
        print("No file, not saved")
    } else {
        let data = NSMutableData()
        let archiver = NSKeyedArchiver(forWritingWith: data)
        // encode data
        archiver.finishEncoding()
            let fileName = globalDocURL.lastPathComponent
            let fileUrl =  = globalAllowedFolderUrl.appendingPathComponent(fileName)
        do {
            try data.write(to: fileUrl, options: [.atomic])
        }  catch {
             Swift.print(error)
            return
        }
   
    }
}

There was no update because you missed my point: you were able to save the bookmark by an accident, but your code was still wrong (AFAICT). I hesitate to provide sample code, because I'm not sure exactly what your requirements are (and it's not my job to do your job), but here:


import Cocoa
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate
{
     func applicationDidFinishLaunching (_ notification: Notification) {
          // Create the Application Support subfolder if necessary
          let fileManager = FileManager.default
          let appSupportURL = fileManager.urls (for: .applicationSupportDirectory, in: .userDomainMask).first!.appendingPathComponent ("com.example.testbookmark")
          do {
               // Note: this will fail after the first time, but the failure will be detected when the bookmark file read is tried
               try fileManager.createDirectory(at: appSupportURL, withIntermediateDirectories: true, attributes: nil)
          }
          catch { }
          // Look for an existing bookmark to the Documents folder
          let bookmarkURL = appSupportURL.appendingPathComponent ("documentsBookmark")
          do {
               let bookmarkData = try Data (contentsOf: bookmarkURL)
               var isStale = false
               let documentsURL = try URL (resolvingBookmarkData: bookmarkData, options: .withSecurityScope, bookmarkDataIsStale: &isStale)!
               _ = documentsURL.startAccessingSecurityScopedResource ()
               logFolderContents (url: documentsURL)
          }
          catch (let e) {
               let error = e as NSError
               guard error.domain == NSCocoaErrorDomain && error.code == CocoaError.Code.fileReadNoSuchFile.rawValue else { print (e); return }
               let openPanel = NSOpenPanel ()
               openPanel.canChooseFiles = false
               openPanel.canChooseDirectories = true
               openPanel.allowsMultipleSelection = false
               openPanel.canCreateDirectories = false
               openPanel.prompt = NSLocalizedString ("Choose", comment: "")
               openPanel.begin {
                   guard $0 == .OK else { return }
                   let documentsURL = openPanel.url!
                   let bookmarkData = try! documentsURL.bookmarkData (options: .withSecurityScope, includingResourceValuesForKeys: nil, relativeTo: nil)
                   try! bookmarkData.write (to: bookmarkURL)
                   self.logFolderContents (url: documentsURL)
              }
          }
     }
     func logFolderContents (url: URL) {
          let fileManager = FileManager.default
          do {
               let contents = try fileManager.contentsOfDirectory (at: url, includingPropertiesForKeys: nil, options: [])
               print (contents.first ?? NSLocalizedString ("No contents", comment: ""))
          }
     catch {
          print (error)
     }
}
}


I left out much of the error checking, and I didn't call stopAccessingSecurityScopedResource.

THANK YOU BOTH!!
QuinceyMorris & Claude31


Do not hesitate, just do it. Because this code help me very much. And it solve my problem. I am always learning something new each day (and that for Swift). And this code is the basic wheel that Apple must publish as sample code. For "open" and "saving". Have a great weekend!