简体   繁体   English

Swift 5:如何读取plist文件中的变量?

[英]Swift 5: How to read variables in plist files?

I searched a way (or a template) how to read variables which are stored in plist files.我搜索了一种方式(或模板)如何读取存储在 plist 文件中的变量。 I saw a few codes, but no code worked with the newest Swift version.我看到了一些代码,但没有代码适用于最新的 Swift 版本。

I'm new to Swift, I actually don't check exactly how it works.. Could anyone be so nice and give me an example?我是 Swift 的新手,实际上我并没有确切地检查它是如何工作的。谁能这么好给我举个例子?

I have a CollectionView and want to display the strings in my plist file.我有一个 CollectionView 并想在我的 plist 文件中显示字符串。 That's my plist file:那是我的 plist 文件:

For every animal key (dictionary type) two sub keys (name and picture).对于每个动物键(字典类型)两个子键(名称和图片)。 Root --> Animals --> Animals1根 --> 动物 --> Animals1

All Keys expept "name" and "picture" are dictionaries.所有 Keys exppt "name" 和 "picture" 都是字典。 Now I want to get the dictionaries and show the name and the picture in my collection view.现在我想获取字典并在我的收藏视图中显示名称和图片。 Later I will add more vars.稍后我将添加更多变量。 I hope it's understandable:'D我希望这是可以理解的:'D

The incomplete code I have:我的不完整代码:

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
    let path = Bundle.main.path(forResource: "Animals", ofType:"plist")!
    let dict = NSDictionary(contentsOfFile: path)
    SortData = dict!.object(forKey: "Animals") as! [Dictionary]
}

Your property list format is not very convenient.您的属性列表格式不是很方便。 As you want an array anyway create the property list with an array for key animals (and name all keys lowercased)因为你想要一个数组,无论如何创建一个带有关键animals数组的属性列表(并将所有键命名为小写)

<?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>animals</key>
    <array>
        <dict>
            <key>name</key>
            <string>Tiger</string>
            <key>picture</key>
            <string>tiger_running</string>
        </dict>
        <dict>
            <key>name</key>
            <string>Jaguar</string>
            <key>picture</key>
            <string>jaguar_sleeping</string>
        </dict>
    </array>
</dict>
</plist>

Then create two structs然后创建两个结构体

struct Root : Decodable {
    let animals : [Animal]
}

struct Animal : Decodable {
    let name, picture : String
}

and the data source array和数据源数组

var animals = [Animal]()

And decode the stuff并解码这些东西

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
    let url = Bundle.main.url(forResource: "Animals", withExtension:"plist")!
    do {
        let data = try Data(contentsOf: url)
        let result = try PropertyListDecoder().decode(Root.self, from: data)
        self.animals = result.animals
    } catch { print(error) }
}

PropertyListDecoder and PropertyListSerialization are state of the art in Swift. PropertyListDecoderPropertyListSerialization是 Swift 中最先进的。 The NSDictionary/NSArray API is objective-c-ish and outdated. NSDictionary/NSArray API 是客观的和过时的。

You could use PropertyListSerialization or NSDictionary as you have done.您可以像以前一样使用 PropertyListSerialization 或 NSDictionary。 Here most probably you have gone wrong due to some other reason.在这里,您很可能由于其他原因而出错。

class ViewController: UIViewController {

    var animals = [String: Any]()

    override func viewDidLoad() {
        super.viewDidLoad()

        fetchAnimals() // or fetchPropertyListAnimals()
        fetchPropertyListAnimals()
    }

    func fetchAnimals() {

        guard let path = Bundle.main.path(forResource: "Animals", ofType: "plist") else {
            print("Path not found")
            return
        }

        guard let dictionary = NSDictionary(contentsOfFile: path) else {
            print("Unable to get dictionary from path")
            return
        }

        if let animals = dictionary.object(forKey: "Animals") as? [String: Any] {
            self.animals = animals
        } else {
            print("Unable to find value for key named Animals")
        }
    }

    func fetchPropertyListAnimals() {
        var propertyListFormat =  PropertyListSerialization.PropertyListFormat.xml
        guard let path = Bundle.main.path(forResource: "Animals", ofType: "plist") else {
            print("Path not found")
            return
        }
        guard let data = FileManager.default.contents(atPath: path) else {
            print("Unable to get data from path")
            return
        }
        do {
            if let animals = try PropertyListSerialization.propertyList(from: data, options: .mutableContainersAndLeaves, format: &propertyListFormat) as? [String: Any] {
                self.animals = animals
            } else {
                print("Unable to find value for key named Animals")
            }

        } catch {
            print("Error reading plist: \(error), format: \(propertyListFormat)")
        }
    }
}
/*
  //Use: let plistData = Bundle().parsePlist(ofName: "Your-Plist-Name")
   ---------- OR ---------
   guard let path = Bundle.main.path(forResource: "GoogleService-Info", ofType: "plist"),
   let myDict = NSDictionary(contentsOfFile: path) else {
   return nil
  }
 let value = myDict.value(forKey: "CLIENT_ID") as! String?
*/

extension Bundle {
    func parsePlist(ofName name: String) -> [String: AnyObject]? {
    // check if plist data available
    guard let plistURL = Bundle.main.url(forResource: name, withExtension: "plist"),
          let data = try? Data(contentsOf: plistURL)
    else { return nil }
    
    // parse plist into [String: Anyobject]
    guard let plistDictionary = try? PropertyListSerialization.propertyList(from: data, options: [], format: nil) as? [String: AnyObject] else {
        return nil
    }
    return plistDictionary
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM