5 Replies
      Latest reply on Jun 14, 2018 9:05 AM by TheCD
      flarosa Level 1 Level 1 (0 points)

        I've been struggling for over an hour now trying to figure out what I'm supposed to do in order to write a Data object to a file in the caches folder. This is something I've done hundreds of times in Objective-C over ten years.


        Here's how I got the reference to the caches folder:

          let paths = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)
          let cachesDirectory: URL = paths[0]


        I then concatenated a filename to it:

        let path = "\(cachesDirectory.absoluteString)/foo.json"


        I then tried various ways to write the data including the Data.write function, the FileManager createFile function, and also by creating a FileHandle and writing to that. In each case the operation fails with an error that says "No such file or directory foo.json" or something to that effect.


        What am I doing wrong?

        • Re: Write Data to a file in Caches folder?
          flarosa Level 1 Level 1 (0 points)

          Answering my own question, it seems that the expression cachesDirectory.absoluteString does not produce a valid pathname as I was expecting.


          I guess that's okay for now, but eventually I'm going to want to inspect the file using the FileManager which I think requires a path.


          How do I take a file URL and get the local path out of it?




            • Re: Write Data to a file in Caches folder?
              OOPer Level 7 Level 7 (3,880 points)

              The property `absoluteString` returns a string representation of URL, for file URLs, it returns a string like "file:...", which cannot be a valid file path.


              If you need a file path, you can use `path`:

                      let fileManager = FileManager.default
                      let urls = fileManager.urls(for: .cachesDirectory, in: .userDomainMask)
                      let cachesDirectoryUrl = urls[0]
                      let fileUrl = cachesDirectoryUrl.appendingPathComponent("foo.json")
                      print(fileUrl.absoluteString) //-> file:///Users/dev/Library/Developer/CoreSimulator/Devices/D456D1E4-0CB4-4CE5-BA19-1FFC3E1D4576/data/Containers/Data/Application/175F94AF-BC12-4159-9EF5-992464640CED/Library/Caches/foo.json
                      let filePath = fileUrl.path
                      print(filePath) //-> /Users/dev/Library/Developer/CoreSimulator/Devices/D456D1E4-0CB4-4CE5-BA19-1FFC3E1D4576/data/Containers/Data/Application/175F94AF-BC12-4159-9EF5-992464640CED/Library/Caches/foo.json
                      if !fileManager.fileExists(atPath: filePath) {
                          let contents = Data()
                          fileManager.createFile(atPath: filePath, contents: contents)
                          print("File \(filePath) created") //-> (On first run)File /Users/dev/Library/Developer/CoreSimulator/Devices/D456D1E4-0CB4-4CE5-BA19-1FFC3E1D4576/data/Containers/Data/Application/175F94AF-BC12-4159-9EF5-992464640CED/Library/Caches/foo.json created
                      } else {
                          print("File \(filePath) already exists")
            • Re: Write Data to a file in Caches folder?
              TheCD Level 3 Level 3 (355 points)

              Which platform are you using? Regardless, try using the newer URL-based methods to construct the path:


                      let cachesDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
                      let path = cachesDirectory.appendingPathComponent("foo.json")
                • Re: Write Data to a file in Caches folder?
                  flarosa Level 1 Level 1 (0 points)

                  Thanks. This helped me write the file, but I'm stuck at the next step.


                  I now want to determine if the file exists, and if so, get its attributes such as its creation date. Unfortunately, the FileManager class works with paths, not URLs. So I need to somehow convert my file URL into a path.


                  I am not seeing how to do this. There's a "path" property of the URL, but it doesn't return the file path, in fact it doesn't return anything.