Home > Software engineering >  Decoding a Plist Dictionary in Swift 5
Decoding a Plist Dictionary in Swift 5

Time:09-10

I'm writing a Mac command line tool in Swift 5 and I'm trying to parse a Plist which contains a nested dictionary of values named "TestValues". I want to add each key pair from this dictionary to an array but I'm just hitting a brick wall.

The Plist looks like this:

<?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>TestValues</key>
    <dict>
        <key>TestString</key>
        <string>This is my test string value</string>
        <key>TestInt</key>
        <integer>4</integer>
        <key>AnotherTestString</key>
        <string>This is my other test string value</string>
        <key>TestBool</key>
        <true/>
    </dict>
</dict>
</plist>

And my code:

struct CustomPrefs: Codable {
    
    var TestValues: [TestValuePrefs]
    
}

struct TestValuePrefs: Codable {
    
    var TestString: String
    var TestInt: Int
    var AnotherTestString: String
    var TestBool: Bool
    
}


func getCustomPrefs() -> CustomPrefs? {
    
    let decoder = PropertyListDecoder()
    let url = URL(fileURLWithPath: "/Library/Preferences/com.test.preferences.plist")
    
    if let data = try? Data(contentsOf: url) {
        if let customPreferences = try? decoder.decode(CustomPrefs.self, from: data) {
            print("Returning custom prefs")
            return customPreferences
        }
    }
    print("Returning nil")
    return nil
    
}


let preferenceArray = (getCustomPrefs()?.TestValues)
print(preferenceArray ?? "")

But I just keep getting nil from the "getCustomPrefs" function. Can anyone see where I'm going wrong?

CodePudding user response:

The TestValues var in CustomPrefs isn't an array or dictionary but rather the TestValuePrefs object.

The following should do the trick:

struct CustomPrefs: Decodable {
    let TestValues: TestValuePrefs
    
    struct TestValuePrefs: Decodable {
        let TestString: String
        let TestInt: Int
        let AnotherTestString: String
        let TestBool: Bool
    }
}

func getCustomPrefs() -> CustomPrefs? {
    let decoder = PropertyListDecoder()
    let url = URL(fileURLWithPath: "/Library/Preferences/com.test.preferences.plist")
    
    do {
        let data = try Data(contentsOf: url)
        let customPreferences = try decoder.decode(CustomPrefs.self, from: data)
        return customPreferences
    }
    catch {
        print("Error: \(error)")
    }
    return nil
}

I'd also recommend using CodingKeys to avoid using capitalized variables.

  • Related