6

I am working to get the contents of an NSData instance written to a file. I am currently using an Xcode playground.

This is my code:

let validDictionary = [
    "numericalValue": 1,
    "stringValue": "JSON",
    "arrayValue": [0, 1, 2, 3, 4, 5]
]

let rawData: NSData!


if NSJSONSerialization.isValidJSONObject(validDictionary) {
    do {
        rawData = try NSJSONSerialization.dataWithJSONObject(validDictionary, options: .PrettyPrinted)
        try rawData.writeToFile("newdata.json", options: .DataWritingAtomic)
    } catch {
        // Handle Error
    }
}

I have a file named newdata.json located in resources but when I check it there is nothing inside. I also tried deleting and seeing if the file will be created but it still doesn't work.

Bartłomiej Semańczyk
  • 59,234
  • 49
  • 233
  • 358
dozo
  • 329
  • 2
  • 5
  • 17

3 Answers3

6

Use following extension:

extension Data {

    func write(withName name: String) -> URL {

        let url = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(name)

        try! write(to: url, options: .atomicWrite)

        return url
    }
}
Bartłomiej Semańczyk
  • 59,234
  • 49
  • 233
  • 358
2

Your code is correct, but the file is not being written where you expect. Swift Playgrounds are sandboxed and the files are in another part of the system, not in your project's resources folder.

You can check that the file is actually being saved by immediately trying to read from it, like so:

let validDictionary = [
    "numericalValue": 1,
    "stringValue": "JSON",
    "arrayValue": [0, 1, 2, 3, 4, 5]
]

let rawData: NSData!


if NSJSONSerialization.isValidJSONObject(validDictionary) { // True
    do {
        rawData = try NSJSONSerialization.dataWithJSONObject(validDictionary, options: .PrettyPrinted)
        try rawData.writeToFile("newdata.json", options: .DataWritingAtomic)

        var jsonData = NSData(contentsOfFile: "newdata.json")
        var jsonDict = try NSJSONSerialization.JSONObjectWithData(jsonData!, options: .MutableContainers)
        // -> ["stringValue": "JSON", "arrayValue": [0, 1, 2, 3, 4, 5], "numericalValue": 1]

    } catch {
        // Handle Error
    }
}

From Tom's comment below: Specifically, the file is in some place like /private/var/folder‌​s/bc/lgy7c6tj6pjb6cx0‌​p108v7cc0000gp/T/com.‌​apple.dt.Xcode.pg/con‌​tainers/com.apple.dt.‌​playground.stub.iOS_S‌​imulator.MyPlayground‌​-105DE0AC-D5EF-46C7-B‌​4F7-B33D8648FD50/newd‌​ata.json.

Tom Harrington
  • 69,312
  • 10
  • 146
  • 170
Carter
  • 3,053
  • 1
  • 17
  • 22
  • 1
    Specifically, the file is in some place like `/private/var/folders/bc/lgy7c6tj6pjb6cx0p108v7cc0000gp/T/com.apple.dt.Xcode.pg/containers/com.apple.dt.playground.stub.iOS_Simulator.MyPlayground-105DE0AC-D5EF-46C7-B4F7-B33D8648FD50/newdata.json`. OS X sandboxing will make it awkward to write it anywhere else. – Tom Harrington Aug 17 '16 at 03:06
  • I found out there's a new approach in Xcode 8. See my answer. – Tom Harrington Aug 25 '16 at 18:31
1

Updated answer, since the old approach of using the "Documents" folder doesn't work any more:

Since you're using Xcode playgrounds, you can use the shared playground data location. You can find this my importing PlaygroundSupport and then using the playgroundSharedDataDirectory URL that it defines:

import PlaygroundSupport

print("Shared location: \(playgroundSharedDataDirectory)")

This gives a directory location you can use in playgrounds, but this directory does not exist until you create it. Before using it, do something like this:

do {
    if !FileManager.default.fileExists(atPath: playgroundSharedDataDirectory.path) {
        try FileManager.default.createDirectory(at: playgroundSharedDataDirectory, withIntermediateDirectories: false)
    }
} catch {
    print("FileManager error: \(error)")
}

Now that the directory exists, you can read and write data there. Use file URLs that are in the shared directory, for example

let testFile = playgroundSharedDataDirectory.appendingPathComponent("test.txt")

Then use it like any normal file URL, for example:

do {
    try greeting.write(to: testFile, atomically: true, encoding: .utf8)
} catch {
    print("Write error: \(error)")
}
Tom Harrington
  • 69,312
  • 10
  • 146
  • 170
  • Hi @Tom , because of this https://stackoverflow.com/questions/75983996/playgrounds-how-to-save-a-file-getting-no-permission , I did see your posting before and did try it; unfortunate it doesn't work. Any Idea why? – iPadawan Apr 11 '23 at 09:40