Search code examples
swiftmacosplistnsfilemanager

Reading a PLIST file Dict of Dict


I am trying to read a plist file which has Dictionary inside Dictionary

Example: ["Name":["Age":"Two", "Height":"Short"]]

This is how I am reading the file:

do {
    let data = try Data(contentsOf: URL(fileURLWithPath: path))
    let dataFromPlist = try PropertyListSerialization.propertyList(from: data, format: nil) as! [String:Any]
    print(dataFromPlist)
    } catch {
      print(error)
    }

But my result print(dataFromPlist) Is returning the following:

["Name": {
Age = 1;
Height = 1;
}]

How do I either convert the result of my current reading method or read the .plist file so that I get back exactly what I saved into it which is:

["Name":["Age":"Two", "Height":"Short"]]


Solution

  • Try setting the format of the dictionary explicitly if you are only working with a nested dictionary that is of type [String:String]:

    let dataFromPlist = try PropertyListSerialization.propertyList(from: data, format: nil) as! [String : [String : String ] ]
    

    Based on your sample data, I created a property list whose source file converts to this in xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
        <key>Name</key>
        <dict>
            <key>Age</key>
            <string>Two</string>
            <key>Height</key>
            <string>Short</string>
        </dict>
    </dict>
    </plist>
    

    The output is as you would like:

    ["Name": ["Height": "Short", "Age": "Two"]]
    

    The full example code with an Example.plist file in the root of the project:

    let urlPath = Bundle.main.url(forResource: "Example", withExtension: "plist")
        if let urlPath = urlPath {
            do {
                let data = try Data(contentsOf: urlPath)
                let dataFromPlist = try PropertyListSerialization.propertyList(from: data, format: nil) as! [String : [String : String ] ]
                print(dataFromPlist)
            } catch {
                print(error)
            }
        }
    }