我在玩苹果的新Swift编程语言,遇到了一些问题…

目前我试图读取一个plist文件,在Objective-C中,我会做以下工作来获取内容作为NSDictionary:

NSString *filePath = [[NSBundle mainBundle] pathForResource:@"Config" ofType:@"plist"];
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:filePath];

我如何得到一个plist作为一个字典在Swift?

我假设我可以得到路径到plist:

let path = NSBundle.mainBundle().pathForResource("Config", ofType: "plist")

当这工作(如果它是正确的?):我如何获得内容作为一个字典?

还有一个更普遍的问题:

是否可以使用默认的NS*类?我想是的……还是我遗漏了什么?据我所知,默认框架NS*类仍然有效,可以使用吗?


当前回答

在我的情况下,我创建了一个NSDictionary称为appSettings并添加所有需要的键。对于这种情况,解决方案是:

if let dict = NSBundle.mainBundle().objectForInfoDictionaryKey("appSettings") {
  if let configAppToken = dict["myKeyInsideAppSettings"] as? String {

  }
}

其他回答

我一直在使用Swift 3.0,并希望为更新的语法贡献一个答案。此外,可能更重要的是,我使用PropertyListSerialization对象来做繁重的工作,这比仅仅使用NSDictionary灵活得多,因为它允许数组作为plist的根类型。

下面是我正在使用的plist的截图。这有点复杂,以便显示可用的功率,但这将适用于任何允许的plist类型组合。

正如你所看到的,我正在使用字符串数组:字符串字典来存储网站名称及其对应的URL列表。

如上所述,我使用PropertyListSerialization对象来为我做繁重的工作。此外,Swift 3.0变得更加“Swifty”,所以所有的对象名称都失去了“NS”前缀。

let path = Bundle.main().pathForResource("DefaultSiteList", ofType: "plist")!
let url = URL(fileURLWithPath: path)
let data = try! Data(contentsOf: url)
let plist = try! PropertyListSerialization.propertyList(from: data, options: .mutableContainers, format: nil)

在上面的代码运行后,plist的类型将是Array<AnyObject>,但我们知道它的实际类型,所以我们可以将它强制转换为正确的类型:

let dictArray = plist as! [[String:String]]
// [[String:String]] is equivalent to Array< Dictionary<String, String> >

现在我们可以以自然的方式访问Array of String:String dictionary的各种属性。希望将它们转换为实际的强类型结构体或类;)

print(dictArray[0]["Name"])

在swift 3.0从Plist读取。

func readPropertyList() {
        var propertyListFormat =  PropertyListSerialization.PropertyListFormat.xml //Format of the Property List.
        var plistData: [String: AnyObject] = [:] //Our data
        let plistPath: String? = Bundle.main.path(forResource: "data", ofType: "plist")! //the path of the data
        let plistXML = FileManager.default.contents(atPath: plistPath!)!
        do {//convert the data to a dictionary and handle errors.
            plistData = try PropertyListSerialization.propertyList(from: plistXML, options: .mutableContainersAndLeaves, format: &propertyListFormat) as! [String:AnyObject]

        } catch {
            print("Error reading plist: \(error), format: \(propertyListFormat)")
        }
    }

阅读更多 如何在swift中使用属性列表(. plist)。

在我的情况下,我创建了一个NSDictionary称为appSettings并添加所有需要的键。对于这种情况,解决方案是:

if let dict = NSBundle.mainBundle().objectForInfoDictionaryKey("appSettings") {
  if let configAppToken = dict["myKeyInsideAppSettings"] as? String {

  }
}

你仍然可以在Swift中使用nsdictionary:

Swift 4

 var nsDictionary: NSDictionary?
 if let path = Bundle.main.path(forResource: "Config", ofType: "plist") {
    nsDictionary = NSDictionary(contentsOfFile: path)
 }

Swift 3+

if let path = Bundle.main.path(forResource: "Config", ofType: "plist"),
   let myDict = NSDictionary(contentsOfFile: path){
    // Use your myDict here
}

以及旧版本的Swift

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

NSClasses仍然可用,完全可以在Swift中使用。我想他们可能很快就会把重点转移到swift上,但是目前swift api并没有核心NSClasses的所有功能。

最好使用本机字典和数组,因为它们已经针对swift进行了优化。也就是说你可以使用NS。我认为这种情况证明了这一点。下面是你如何实现它:

var path = NSBundle.mainBundle().pathForResource("Config", ofType: "plist")
var dict = NSDictionary(contentsOfFile: path)

到目前为止(在我看来),这是访问plist最简单和最有效的方法,但在未来,我希望苹果将添加更多的功能(比如使用plist)到本地字典中。