isaac isaac - 10 months ago 40
iOS Question

Why NSMutableDictionary won't write to file

Forgive the mixing of legacy classes and Swift 3, but why doesn't this work?

let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let documents = paths[0] as String
let path = documents.appending("/SomeData.plist")
let url : URL = URL.init(string: path)!

let sampleDict : NSMutableDictionary = ["name" : "somebody", "age" : "30 ", "food" : "taco"]

let manager = FileManager.default
if (manager.fileExists(atPath: url.absoluteString)) {

sampleDict.write(to: url, atomically: true)

} else {

manager.createFile(atPath: url.absoluteString, contents: nil, attributes: nil)
sampleDict.write(to: url, atomically: true)

The file is created at the path, but writing the contents of the dictionary fails every time.

Answer Source

URLs in the file system must be created with

let url = URL(fileURLWithPath: path)

The URL is always non optional.

And a file system URL must be checked with

if (manager.fileExists(atPath: url.path)) {...

URL(string: (no init) and .absoluteString are related to URLs with a different scheme as file for example http or ftp

Don't annotate types unless the compiler really needs it, for example

let sampleDict = ["name" : "somebody", "age" : "30 ", "food" : "taco"]

If you want a mutable dictionary use var rather than let

PS: Modern syntax

let manager = FileManager.default
let documentURL = try! manager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
let url = documentURL.appendingPathComponent("SomeData.plist")
let sampleDict = ["name" : "somebody", "age" : "30 ", "food" : "taco"]
do {
  let data = try sampleDict, format: .xml, options: 0)
  try data.write(to: url)
} catch let error as NSError {

Explicitly creating a new file is not needed.