【问题标题】:How to Read Plist without using NSDictionary in Swift?如何在 Swift 中不使用 NSDictionary 读取 Plist?
【发布时间】:2017-03-19 03:02:52
【问题描述】:

我已经在 Swift 2 中使用过这个方法

var myDict: NSDictionary?
if let path = NSBundle.mainBundle().pathForResource("Config", ofType: "plist") {
myDict = NSDictionary(contentsOfFile: path)
}

但是不知道如何在 Swift3 中读取 plist 而不使用 NSDictionary(contentsOfFile: 路径)

【问题讨论】:

  • 您的问题是什么?你想达到什么目标?
  • 上述代码需要swift3转换

标签: ios swift dictionary swift3 nsdictionary


【解决方案1】:

在现代 Swift 环境中,我使用这样的东西:

import Foundation

public extension Bundle {

  func plist<As>(from resource: String) -> As? where As: Decodable {
    guard let plist = Bundle.main.url(forResource: resource, withExtension: "plist") else { return nil }
    let decoder = PropertyListDecoder()
    do {
      let data = try Data(contentsOf: plist)
      return try decoder.decode(As.self, from: data)
    } catch { return nil }
  }

}

【讨论】:

    【解决方案2】:

    原生 Swift 方式是使用PropertyListSerialization

    if let url = Bundle.main.url(forResource:"Config", withExtension: "plist") {
       do {
         let data = try Data(contentsOf:url)
         let swiftDictionary = try PropertyListSerialization.propertyList(from: data, format: nil) as! [String:Any]
          // do something with the dictionary
       } catch {
          print(error)
       }
    }
    

    您也可以使用NSDictionary(contentsOf: 进行类型转换:

    if let url = Bundle.main.url(forResource:"Config", withExtension: "plist"),
       let myDict = NSDictionary(contentsOf: url) as? [String:Any] {
       print(myDict)
    }
    

    但您明确写道:不使用 NSDictionary(contentsOf...

    基本上不使用NSDictionary 而不在 Swift 中进行强制转换,您将丢弃重要的类型信息。


    同时(Swift 4+)还有更舒适的PropertyListDecoder,它能够直接将 Plist 解码为模型。

    【讨论】:

    • 所以要以原生方式使用 Dictionary,我必须使用 PropertyListSerialization
    • @vadian 我要补充一点,import Foundation 是在本机 Swift 下工作所必需的。
    • @dinesharjani 是的,但FoundationDataPropertyListSerialization 也是必需的,所以我们可以假设它无论如何都是导入的。
    • @vadian 如果你正在做一个像Perfect 这样的服务器端项目,Foundation 不会自动为你导入 :) 我的思考过程是捕捉“复制粘贴-行不通——继续用谷歌搜索”那种会绕圈子的人(或女孩),因为他们会错过导入。就是这样。
    【解决方案3】:

    PropertyListDecoder可用于将plist文件直接解码为Objects。

    1:示例 Plist 文件 (sample.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>key1</key>
        <string>valua for key1</string>
        <key> key2</key>
        <string>valua for key1</string>
        <key>CustomClass1</key>
        <dict>
            <key>customClass1_key</key>
            <string>customClass1_value</string>
        </dict>
        <key>CustomClass2</key>
        <dict>
            <key>customClass2_kek</key>
            <string>customClasse_value</string>
        </dict>
    </dict>
    </plist>
    

    2:plist 的核心模型

    struct PlistConfiguration: Codable {
        var key1:String?
        var customClass1Obj: CustomClass1?
        var customClass2Obj: CustomClass2?
        
        private enum CodingKeys : String, CodingKey {
                  case key1 = "key1"
                  case customClass1Obj = "CustomClass1"
                  case customClass2Obj = "CustomClass2"
        }
        
    }
    

    2.1:嵌套模型

    struct CustomClass1: Codable {
        var customClass1_key:String?
        private enum CodingKeys : String, CodingKey {
                  case customClass1_key = "customClass1_key"
        }
        
    }
    

    2.2:嵌套模型

    struct CustomClass2: Codable {
        var customClass2_key: String?
        private enum CodingKeys : String, CodingKey {
                  case customClass2_key = "customClass2_key"
        }
        
    }
    

    3:从主应用程序包中读取 Plist

    func parseConfig() -> PlistConfiguration {
            let url = Bundle.main.url(forResource: "sample", withExtension: "plist")!
            let data = try! Data(contentsOf: url)
            let decoder = PropertyListDecoder()
            return try! decoder.decode(PlistConfiguration.self, from: data)
        }
    

    【讨论】:

    • 你节省了我的时间。但是.. parseConfig() 的返回不应该是 PlistConfiguration 而不是 SKDConfiguration?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-25
    • 2017-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多