NSDictionary init(contentsOfFile:) is deprecated so now what?
Asked Answered
I

1

6

Recently (as of iOS 11), init(contentsOfFile:) in NSDictionary became deprecated.

enter image description here

I wanted to be a forward-thinking citizen, so I looked for another way to load a property list (plist) into a NSDictionary type. The only thing I could find was PropertyListSerialization but it is cumbersome comparatively.

This is what I came up with to show the difference:

func dealWithFakeConf(atPath path:String) {
    // So easy!
    let myD:Dictionary<String,Any> = NSDictionary.init(contentsOfFile: path) as! Dictionary<String, Any>
    let l = myD["location"] as? String ?? "BAD_STRING"
    let q = myD["quantity"] as! Int
    print("location = \(l)")
    print("quantity = \(q.description)")

    // Old is new again?!
    guard let rawData = FileManager.default.contents(atPath: path) else {
        fatalError("Sumpin done gone wrong!")
    }
    var format = PropertyListSerialization.PropertyListFormat.xml
    let data = try? PropertyListSerialization.propertyList(from:rawData, options:[.mutableContainers], format:&format)
    guard let realData = data as? Dictionary<String,Any> else {
        fatalError("OMG! Now what?")
    }
    locationLabel.text = realData["location"] as? String ?? "BAD_STRING"
    let qty:Int? = realData["quantity"] as? Int
    quantityLabel.text = qty?.description
}

I noticed that this answer over here has golfed the use of PropertyListSerialization down to less code that what I came up with, but that is not obvious when reading Apple's 7 year old docs Property List Programming Guide. And that example is still 3 indentations deep.

Am I missing a replacement convenience initializer somewhere else? Is this what we do now to load a plist into a Dictionary?

Isodynamic answered 12/7, 2017 at 16:40 Comment(2)
It's deprecated as of iOS 11, not iOS 10.Strander
Thanks @Strander I have fixed tag & text to reflect your confident comment.Isodynamic
B
7

That's not a fair comparison.

Actually the literal translation of

let myD = NSDictionary(contentsOfFile: path) as! [String : Any]

is

let rawData = try! Data(contentsOf: URL(fileURLWithPath: path))
let realData = try! PropertyListSerialization.propertyList(from: rawData, format: nil) as! [String:Any]

In both cases the code crashes if something goes wrong.

However in both cases you should do proper error handling.

Besetting answered 12/7, 2017 at 18:8 Comment(1)
Thanks for golfing the code down. I appreciate that. I can skip the FileManager step. But if I'm doing the same thing in both cases (not handling error conditions), then that is a fair comparison, right?Isodynamic

© 2022 - 2024 — McMap. All rights reserved.