raistlin
raistlin

Reputation: 4346

iOS Document folder is not a directory and/or is missing

Trying to archive an array of Codable elements.

do {
   let data = try PropertyListEncoder().encode(elements)
   let success = NSKeyedArchiver.archiveRootObject(data, toFile:self.archiveURL.path)
   print(success ? "Successful save" : "Save Failed")
} catch {
   print("Save Failed")
}

For some reason path (archiveURL) is constantly wrong:

let archiveURL = FileManager().urls(for: .documentDirectory, in: .userDomainMask).first!

is returning always URL like this:

file:///Users/userName/Library/Developer/CoreSimulator/Devices/deviceID/data/Documents

but searching through folders I see no /Documents folder. Has something changed recently? It used to work few weeks back (pretty sure). Super annoying and I can't find any workaround/fix for that.

Upvotes: 3

Views: 4983

Answers (3)

ChaosCoder
ChaosCoder

Reputation: 3255

This happens in Simulators running iOS 11.x and up.

Before iOS 11, the Simulator created the global (app independent) Documents folder on startup. Since iOS 11.x (don't know if it was a special point release), this does not happen anymore.

Be aware that NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first returns this global documents path only in (unit) tests, not when running the app. If you run the app, you get the application specific Documents folder which is still created when installing the app in the simulator.

This seems to be a bug on Apple side. If you run into this issue (as it seems you have), please file a bug report at https://developer.apple.com/bug-reporting/.

Upvotes: 3

vadian
vadian

Reputation: 285290

You cannot (over)write the Documents directory, you have to append a file name.

And why do you archive the data? You can write the property list data directly to disk.

And never ever print a meaningless literal string in the catch clause, print at least the actual error.

let fileName = "myPropertyList.plist"
let fileURL = archiveURL.appendingPathComponent(fileName)
do {
   let data = try PropertyListEncoder().encode(elements)
   try data.write(to: fileURL)
} catch {
   print("Save Failed", error)
}

Upvotes: 1

Gereon
Gereon

Reputation: 17882

I believe this is a (new-ish) "feature" of the iOS simulators - not all of the ususal directories exist when an app is initially installed.

Fortunately it's easy to create them, e.g. for the applicationSupport directory I do this in my apps:

let fileManager = FileManager.default
let directory = NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true).first!
if !fileManager.fileExists(atPath: directory) {
  try fileManager.createDirectory(atPath: directory, withIntermediateDirectories: true, attributes: nil)
}

Upvotes: 3

Related Questions