2

Hi so here's the boilerplate code for parsing JSON files in Swift 2. Ive used this before and it works but for some reason its broken in the latest version of Xcode 7.1 and Swift 2. Any thoughts about this guys? The error is "Argument labels '(contentsOfFile:, options:, error:)' do not match any available overloads"

import Foundation

extension Dictionary {
    static func loadJSONFromBundle(filename: String) -> Dictionary<String, AnyObject>? {
        if let path = NSBundle.mainBundle().pathForResource(filename, ofType: "json") {

            var error: NSError?
            let data = NSData(contentsOfFile: path, options: NSDataReadingOptions, error: &error)
            if let data = data {
                let dictionary: AnyObject? = NSJSONSerialization.JSONObjectWithData(data,
                    options: NSJSONReadingOptions(), error: &error)
                if let dictionary = dictionary as? Dictionary<String, AnyObject> {
                    return dictionary
                } else {
                    print("Level file '\(filename)' is not valid JSON: \(error!)")
                    return nil
                }
            } else {
                print("Could not load level file: \(filename), error: \(error!)")
                return nil
            }
        } else {
            print("Could not find level file: \(filename)")
            return nil
        }
    }
}
William Kinaan
  • 28,059
  • 20
  • 85
  • 118
m.umar
  • 855
  • 4
  • 13
  • 23
  • How we use NSJSONSerialization has changed in Swift 2. [Example here.](http://stackoverflow.com/questions/31805045/how-to-parse-json-in-swift-2-0-using-nsurlsession) There's plenty other examples on SO. – Eric Aya Oct 29 '15 at 11:22

1 Answers1

6

You were using a not up to date swift code,

I corrected your code, notice that you should select the best NSDataReadingOption that suites u, i choose NSDataReadingOptions.DataReadingMapped

Plus some api don't take the error as an input, so i deleted it.

Notice that when you catch the error, you can use the object error which having it declared explicitly, that is why i removed your error variable

Finally, the new apis for parsing json, should be in a try catch, that is why i added a try catch

import Foundation

extension Dictionary {
    static func loadJSONFromBundle(filename: String) -> Dictionary<String, AnyObject>? {
        if let path = NSBundle.mainBundle().pathForResource(filename, ofType: "json") {


            do{
                let data = try NSData(contentsOfFile: path, options: NSDataReadingOptions.DataReadingMapped)
                do{
                    let dictionary: AnyObject? = try NSJSONSerialization.JSONObjectWithData(data,
                        options: NSJSONReadingOptions())
                    if let dictionary = dictionary as? Dictionary<String, AnyObject> {
                        return dictionary
                    } else {
                        print("Level file '\(filename)' is not valid JSON")
                        return nil
                    }
                }catch {
                    print("Level file '\(filename)' is not valid JSON: \(error)")
                    return nil
                }


            }catch {
                print("Could not load level file: \(filename), error: \(error)")
                return nil
            }

        } else {
            print("Could not find level file: \(filename)")
            return nil
        }
    }
}

So basically:

  1. The NSData(contentsOfFile: path, options: doesn't take error anymore.
  2. The dictionary: AnyObject? = try NSJSONSerialization.JSONObjectWithData(data, options doesn't take error anymore.
  3. Getting NSData from file needs a try catch
  4. Getting json object from NSData needs a try catch
William Kinaan
  • 28,059
  • 20
  • 85
  • 118
  • where can i find the updated guide for all the changes in Swift 2. Here's another thing error im running into. 'enumerate' is unavailable: call the 'enumerate()' method on the sequence – m.umar Oct 29 '15 at 12:13
  • if let dictionary = Dictionary.loadJSONFromBundle(filename) { if let tilesArray: AnyObject = dictionary["tiles"] { for (row, rowArray) in enumerate(tilesArray as! [[Int]]) { – m.umar Oct 29 '15 at 12:14
  • @SheikhMuhammadUmar i believe apply documentation is enough. Nevertheless create a new question about your new problem, and send me the link, i will try to help – William Kinaan Oct 29 '15 at 12:20
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/93681/discussion-between-sheikh-muhammad-umar-and-william-kinaan). – m.umar Oct 29 '15 at 12:30