2017-08-02 405 views
3

我试图使用PropertyListDecoder()来解码plist,但是当我试图访问密钥时,出现一个错误,指出它的格式不正确。我对我做错的事情感到不知所措。我假设我可以解码一个Plist文件的方式,我可以解码一个JSON文件的权利?我不知道,我还是这个新手。解码PropertyList使用Swift 4 Codable PropertyListDecoder()

//struct for PLists 
struct AccessControl: Decodable { 
    enum AccessControlKeys: String, CodingKey { 
     case api 
    } 

    enum KeySecretKeys: String, CodingKey { 
     case apiKey = "KEY" 
     case apiSecret = "SECRET" 
    } 

    var KEYS: [KeySecrets] 
//custom decoder 
    init(from decoder: Decoder) throws { 
     let accessContainer = try decoder.container(keyedBy: AccessControlKeys.self) 
     let nestedContainer = try accessContainer.nestedContainer(keyedBy: KeySecretKeys.self, forKey: .api) 
     self.KEYS = try nestedContainer([KeySecrets].self, forKey: .apiKey) 
     self.KEYS = try nestedContainer.decode([KeySecrets].self, forKey: .apiSecret) 
    } 
} 

struct KeySecrets: Decodable { 
    var apiKey: String 
    var apiSecret: String 
} 



func provideAccessKeys(for api: apis = .api, mode: modes = .dev) -> keysForApi? { 
    switch api { 
    case .api: 
     print("Api") 
    } 
    switch mode { 
    case .dev: 
     print("mode - developers") 
    case .test: 
     print("mode - test") 
    case .prod: 
     print("mode - production") 
    } 
} 

这是我在这第一种方法,但它会抛出一个错误说

“中的数据无法读取,因为它是格式不正确”

if let fileURL = Bundle.main.url(forResource: "Accesscontrol", withExtension: "plist") { 
    do { 
     let data = try Data.init(contentsOf: fileURL, options: .mappedIfSafe) 
     let decoder = PropertyListDecoder() 
     let result = try decoder.decode(AccessControl.self, from: data) 

    } catch { 
     print(error.localizedDescription) 
    } 
} 

第二种方法,刚刚放弃了Codable所有在一起,仍然不能拉出数值

guard let fileUrl = Bundle.main.url(forResource: "Accesscontrol", withExtension: "plist") else {return} 
let key: String 
let secret: String 
do { 
    let data = try Data.init(contentsOf: fileUrl, options: .mappedIfSafe) 
    let plist = try! PropertyListSerialization.propertyList(from:data, options: [], format: nil) as! [Any] 
    print(plist) 
    let dictionary = plist[api.rawValue] 

} catch { 
    print(error.localizedDescription) 
} 

plist文件的结构类似于

<plist version="1.0"> 
<dict> 
    <key>A_GROUP_OF_KEYS</key> 
    <array> 
     <dict> 
      <key>KEY1</key> 
      <string>KEY1_STRING</string> 
      <key>SECRET1_KEY</key> 
      <string>SECRET1_STRING</string> 
     </dict> 
     <dict> 
     <key>KEY2</key> 
     <string>KEY2_STRING</string> 
     <key>SECRET2_KEY</key> 
     <string>SECRET2_VALUE</string> 
     </dict> 
     <dict> 
     <key>KEY</key> 
     <string>KEY_STRING</string> 
     <key>SECRET_KEY</key> 
     <string>SECRET_VALUE</string> 
     </dict> 
    </array> 
<key>ANOTHER_GROUP_OF_KEYS</key> 
    <array> 
     <dict> 
      <key>KEY1</key> 
      <string>KEY1_STRING</string> 
      <key>SECRET1_KEY</key> 
      <string>SECRET1_STRING</string> 
     </dict> 
     <dict> 
     <key>KEY2</key> 
     <string>KEY2_STRING</string> 
     <key>SECRET2_KEY</key> 
     <string>SECRET2_VALUE</string> 
     </dict> 
     <dict> 
     <key>KEY</key> 
     <string>KEY_STRING</string> 
     <key>SECRET_KEY</key> 
     <string>SECRET_VALUE</string> 
     </dict> 
    </array> 
</dict> 
</plist> 

有什么建议?

+0

我不知道这是否是在plist中或你错过了关闭字典在这里,而粘贴 –

+0

这不是一个有效的plist。你可以编辑它吗?当事情到处都很难得到plist文件的结构。另外,添加你的'AccessControl'类的定义/ struct –

+0

我更新了这篇文章。 – SirCJ

回答

1

您的plist文件格式不正确,因此无法解码。您不会使用不同的密钥名称命名每个密钥,例如KEY1KEY2,KEY3等。您为密钥key使用一个名称,并将实际名称放在值字段中。 secret也是如此。

这里有一个更好的plist文件:

<?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>A_GROUP_OF_KEYS</key> 
    <array> 
     <dict> 
      <key>key</key> 
      <string>KEY1_STRING</string> 
      <key>secret</key> 
      <string>SECRET1_STRING</string> 
     </dict> 
     <dict> 
      <key>key</key> 
      <string>KEY2_STRING</string> 
      <key>secret</key> 
      <string>SECRET2_VALUE</string> 
     </dict> 
     <dict> 
      <key>key</key> 
      <string>KEY3_STRING</string> 
      <key>secret</key> 
      <string>SECRET3_VALUE</string> 
     </dict> 
    </array> 
    <key>ANOTHER_GROUP_OF_KEYS</key> 
    <array> 
     <dict> 
      <key>key</key> 
      <string>KEY1_STRING</string> 
      <key>secret</key> 
      <string>SECRET1_STRING</string> 
     </dict> 
     <dict> 
      <key>key</key> 
      <string>KEY2_STRING</string> 
      <key>secret</key> 
      <string>SECRET2_VALUE</string> 
     </dict> 
     <dict> 
      <key>key</key> 
      <string>KEY3_STRING</string> 
      <key>secret</key> 
      <string>SECRET3_VALUE</string> 
     </dict> 
    </array> 
</dict> 
</plist> 

解码,这是死的简单:

struct AccessControl: Decodable { 
    struct Key: Decodable { 
     var key: String 
     var secret: String 
    } 

    var keyGroup1: [Key] 
    var keyGroup2: [Key] 

    enum CodingKeys: String, CodingKey { 
     case keyGroup1 = "A_GROUP_OF_KEYS" 
     case keyGroup2 = "ANOTHER_GROUP_OF_KEYS" 
    } 
} 
+0

我确实设法在格式正确的Plist上进行测试。我试图重写它。这并没有解决,但你的解决方案。没有正确设置我的Swift模型来接收Decoded Plist。 – SirCJ