I want to fetch data from property list and the structure of the property list is like this
this is the source file as xml
<array>
<dict>
<key>imageIcon</key>
<string>air-compressor.png</string>
<key>toolsName</key>
<string>Air Compressor</string>
<key>items</key>
<array>
<dict>
<key>item</key>
<string>Air Compressor 1</string>
<key>borrower</key>
<string></string>
</dict>
<dict>
<key>item</key>
<string>Air Compressor 2</string>
<key>borrower</key>
<string></string>
</dict>
</array>
</dict>
</array>
</plist>
and I structure my object model like this
struct ToolsItem: Codable {
var tools: [Tools]
}
struct Tools: Codable {
let imageIcon: String
let toolsName: String
var items: [Items]
}
struct Items: Codable {
let itemName: String
let borrower: String
}
and set my data manager like this
class DataManager {
static let shared = DataManager()
func fetch() {
guard let path = Bundle.main.path(forResource: "ToolsData", ofType: "plist") else { return }
let url = URL(fileURLWithPath: path)
do {
let data = try Data(contentsOf: url)
let items = try PropertyListDecoder().decode(ToolsItem.self, from: data)
print(items.tools)
} catch {
print(error)
}
}
}
but it return
"Expected to decode Dictionary<String, Any> but found an array instead." and no data being show.
if change my data manager like this
let items = try PropertyListDecoder().decode([ToolsItem].self, from: data)
The error return
keyNotFound(CodingKeys(stringValue: "tools", intValue: nil), Swift.DecodingError.Context(codingPath: [_PlistKey(stringValue: "Index 0", intValue: 0)], debugDescription: "No value associated with key CodingKeys(stringValue: "tools", intValue: nil) ("tools").", underlyingError: nil))
How to fetch data from plist correctly?
Your struct should be the following.
import Foundation
struct ToolsItem: Codable {
let imageIcon: String
let toolsName: String
let items: [Items]
}
struct Items: Codable {
let item: String
let borrower: String
}
// For the view controller //
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if let path = Bundle.main.path(forResource: "ToolsData", ofType: "plist") {
let fileURL = URL(fileURLWithPath: path)
do {
let data = try Data(contentsOf: fileURL)
let items = try PropertyListDecoder().decode([ToolsItem].self, from: data)
print("Items: \(items)")
} catch let error as NSError {
print("\(error)")
}
}
}