0

Swift 4.0 iOS 11.2.x

I created a Codable stuct called products here and used this method to save it to file.

 func saveImage() {
    let documentsDirectoryURL = try! FileManager().url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
    let file2ShareURL = documentsDirectoryURL.appendingPathComponent("config.n2kHunt")

    var json: Any?
    let encodedData = try? JSONEncoder().encode(products)
    if let data = encodedData {
        json = try? JSONSerialization.jsonObject(with: data, options: .allowFragments)
        if let json = json {
            do {
                try String(describing: json).write(to: file2ShareURL, atomically: true, encoding: .utf8)
            } catch {
                print("unable to write")
            }
        }
    }
}

It works and assuming I enter two records I get this on file. [which isn't json, but whatever].

(
    {
    identity = "blah-1";
    major = 245;
    minor = 654;
    url = "https://web1";
    uuid = f54321;
},
    {
    identity = "blah-2";
    major = 543;
    minor = 654;
    url = "https://web2";
    uuid = f6789;
}

)

I airdrop the file to a second iOS device, where I try and decode it with this procedure in appDelegate.

func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {

    do {
        let string2D = try? String(contentsOf: url)
        let jsonData = try? JSONSerialization.data(withJSONObject: string2D)
        do {
            products = try JSONDecoder().decode([BeaconDB].self, from: jsonData!)
        } catch let jsonErr {
            print("unable to read \(jsonErr)")
        }

    }  catch {
        print("application error")
    }
   }

And I get a mother crash, with this error message...

2018-03-06 21:20:29.248774+0100 blah[2014:740956] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '* +[NSJSONSerialization dataWithJSONObject:options:error:]: Invalid top-level type in JSON write'

What am I doing wrong; how can I write json to a file such that I can read it back!! Ironically I made this code work with a plist a few days back, I hate json.

0

1 Answer 1

3

Why do you encode the struct to JSON, then deserialize the JSON to Swift Array and save the collection type string representation(!) to disk? The other way round cannot work and that causes the error.

It's much easier:

func saveImage() {
    let documentsDirectoryURL = try! FileManager().url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
    let file2ShareURL = documentsDirectoryURL.appendingPathComponent("config.n2kHunt")

    do {
        let encodedData = try JSONEncoder().encode(products)
        try encodedData.write(to: file2ShareURL)
    } catch {
        print("unable to write", error)
    }
}

func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {

    do {
        let jsonData = try Data(contentsOf: url)
        products = try JSONDecoder().decode([BeaconDB].self, from: jsonData)
    } catch {
        print("unable to read", error)
    }
}

Notes:

  • Never print a meaningless literal string in a catch clause, print at least the actual error.
  • Never write try? in a do - catch block. Write try without question mark to do catch the errors.
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks Vadian; I just got to this code, only mine isn't quite as good as yours with Try? and this and that! Now works!!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.