我在玩苹果的新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*类仍然有效,可以使用吗?


当前回答

我一直在使用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"])

其他回答

以下是我找到的解决方案:

let levelBlocks = NSDictionary(contentsOfFile: NSBundle.mainBundle().pathForResource("LevelBlocks", ofType: "plist"))
let test: AnyObject = levelBlocks.objectForKey("Level1")
println(test) // Prints the value of test

我将测试类型设置为AnyObject,以关闭关于可能发生的意外推断的警告。

而且,它必须在类方法中完成。

访问并保存已知类型的特定值:

let value = levelBlocks.objectForKey("Level1").objectForKey("amount") as Int
println(toString(value)) // Converts value to String and prints it

访问plist文件的简单结构(Swift 2.0)

struct Configuration {      
  static let path = NSBundle.mainBundle().pathForResource("Info", ofType: "plist")!
  static let dict = NSDictionary(contentsOfFile: path) as! [String: AnyObject]

  static let someValue = dict["someKey"] as! String
}

用法:

print("someValue = \(Configuration.someValue)")

你可以使用它,我在github https://github.com/DaRkD0G/LoadExtension中创建了一个简单的字典扩展

extension Dictionary {
    /**
        Load a Plist file from the app bundle into a new dictionary

        :param: File name
        :return: Dictionary<String, AnyObject>?
    */
    static func loadPlistFromProject(filename: String) -> Dictionary<String, AnyObject>? {

        if let path = NSBundle.mainBundle().pathForResource("GameParam", ofType: "plist") {
            return NSDictionary(contentsOfFile: path) as? Dictionary<String, AnyObject>
        }
        println("Could not find file: \(filename)")
        return nil
    }
}

你可以用它来计算负载

/**
  Example function for load Files Plist

  :param: Name File Plist
*/
func loadPlist(filename: String) -> ExampleClass? {
    if let dictionary = Dictionary<String, AnyObject>.loadPlistFromProject(filename) {
        let stringValue = (dictionary["name"] as NSString)
        let intergerValue = (dictionary["score"] as NSString).integerValue
        let doubleValue = (dictionary["transition"] as NSString).doubleValue

        return ExampleClass(stringValue: stringValue, intergerValue: intergerValue, doubleValue: doubleValue)
    }
    return nil
}

你仍然可以在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的所有功能。

斯威夫特3.0

if let path = Bundle.main.path(forResource: "config", ofType: "plist") {
    let dict = NSDictionary(contentsOfFile: path)

    // use dictionary
}

在我看来,这是最简单的方法。