How to read from a plist with Swift 3 iOS app
Same way you have done in Swift 2.3 or lower just syntax is changed.
if let path = Bundle.main.path(forResource: "fileName", ofType: "plist") { //If your plist contain root as Array if let array = NSArray(contentsOfFile: path) as? [[String: Any]] { } ////If your plist contain root as Dictionary if let dic = NSDictionary(contentsOfFile: path) as? [String: Any] { }}
Note: In Swift it is better to use Swift's generic type Array and Dictionary instead of NSArray
and NSDictionary
.
Edit: Instead of NSArray(contentsOfFile: path)
and NSDictionary(contentsOfFile:)
we can also use PropertyListSerialization.propertyList(from:)
to read data from plist
file.
if let fileUrl = Bundle.main.url(forResource: "fileName", withExtension: "plist"), let data = try? Data(contentsOf: fileUrl) { if let result = try? PropertyListSerialization.propertyList(from: data, options: [], format: nil) as? [[String: Any]] { // [String: Any] which ever it is print(result) }}
As Swift 4 introduces Codable
Step 1: Load the Plist File from bundle.
Step 2: Use PropertyListDecoder for the decoding of property list values into semantic Decodable
types.
Step 3: Create Codable Struct
Complete code -
func setData() { // location of plist file if let settingsURL = Bundle.main.path(forResource: "JsonPlist", ofType: "plist") { do { var settings: MySettings? let data = try Data(contentsOf: URL(fileURLWithPath: settingsURL)) let decoder = PropertyListDecoder() settings = try decoder.decode(MySettings.self, from: data) print("toolString is \(settings?.toolString ?? "")") print("DeviceDictionary is \(settings?.deviceDictionary?.phone ?? "")") print("RootPartArray is \(settings?.RootPartArray ?? [""])") } catch { print(error) } } }}struct MySettings: Codable { var toolString: String? var deviceDictionary: DeviceDictionary? var RootPartArray: [String]? private enum CodingKeys: String, CodingKey { case toolString = "ToolString" case deviceDictionary = "DeviceDictionary" case RootPartArray } struct DeviceDictionary: Codable { var phone: String? init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) phone = try values.decodeIfPresent(String.self, forKey: .phone) } } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) toolString = try values.decodeIfPresent(String.self, forKey: .toolString) deviceDictionary = try values.decodeIfPresent(DeviceDictionary.self, forKey: .deviceDictionary) RootPartArray = try values.decodeIfPresent([String].self, forKey: .RootPartArray) }}
Sample Plist file -> https://gist.github.com/janeshsutharios/4b0fb0e3edeff961d3e1f2829eb518db
Here is a Swift 3 implementation, based on Nirav D's answer:
/// Read Plist File. /// /// - Parameter fileURL: file URL. /// - Returns: return plist content. func ReadPlist(_ fileURL: URL) -> [String: Any]? { guard fileURL.pathExtension == FileExtension.plist, let data = try? Data(contentsOf: fileURL) else { return nil } guard let result = try? PropertyListSerialization.propertyList(from: data, options: [], format: nil) as? [String: Any] else { return nil } print(result) return result }