RickyTheCoder
RickyTheCoder

Reputation: 93

How to write JSON to file locally with FileManger and JSONEncoder? Swift

So want I'm trying to do is write json created in code to the user local documents directory but can seem to get this to work.

struct Puzzle: Codable {
  let id: Int?
  let puzzle: Int?
  let moves: Int?
}

class PuzzleController: UIViewController {

  override func viewDidLoad() {
    super.viewDidLoad()

    // create reference to default filemanager object
    let filemgr = FileManager.default

    // get documents directory path
    let dirPath = filemgr.urls(for: .documentsDirectory, in: .userDomainMask)
    let docsDir = dirPath[0].path

    // change to current working directory
    filemgr.changeCurrentDirectoryPath(docsDir)

    // create a new directory
    let docsURL = dirPath[0]
    let newDir = docsURL.appendingPathComponent("json").path

    do {
      try filemgr.createDirectory(atPath: newDir, withIntermediateDirectories: true, attributes: nil)
    } catch let error as NSError {
      print(error.localizeDescription)
    }

    // create arrary of json objects
    let jsonPuzzle = [Puzzle(id: 1, puzzle: 1, moves: 1), Puzzle(id: 2, puzzle: 2, moves: 2), Puzzle(id: 3, puzzle: 3, moves: 3)] 

    // create url to json file
    let jURL = URL(string: newDir)?.appendingPathComponent("pjson.json")

    // write to json file
    do {
      let encoder = JSONEncoder()
      encoder.outputFormatting = .prettyPrinted
      let jsonData = try encoder.encode(jsonPuzzle)
      try jsonData.write(to: jURL)
    } catch let jError {
      print(jError)
    }
  }
}  

I keep getting CFURLCopyResourcePropertyForKey failed because it was passed an URL which has no scheme and Error Domain=NSCocoaErrorDomain Code=518 "The file couldn’t be saved because the specified URL type isn’t supported."

What am I doing wrong? What is the proper steps needed to write json to a file locally without using a third party api?

The contents of jURL as requested by one of the commenters. "/Users/blank/Library/Developer/CoreSimulator/Devices/920F6A0F-E814-49E2-A792-04605361F139/data/Containers/Data/Applicatio ... ir/pjson"

Upvotes: 0

Views: 528

Answers (1)

Joakim Danielson
Joakim Danielson

Reputation: 51851

The problem is that you lose the protocol (scheme) when you switch back and forth between URL and String for your paths, using only URL will fix your error.

Here is a shortened version of your code that only uses URL for directory and file paths to make sure the URL is valid

let filemgr = FileManager.default

let dirPath = filemgr.urls(for: .documentsDirectory, in: .userDomainMask)

let docsURL = dirPath[0]
let newDir = docsURL.appendingPathComponent("json")

do {
  try filemgr.createDirectory(at: newDir, withIntermediateDirectories: true, attributes: nil)
} catch {
  print(error)
}

let jURL = newDir.appendingPathComponent("pjson.json")

Upvotes: 2

Related Questions