How do I get a plist as a Dictionary in Swift?
In swift 3.0 Reading from 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)")
}
}
Read More
HOW TO USE PROPERTY LISTS (.PLIST) IN SWIFT.
iOS Framework - get plist into a dictionary
Use
let path = Bundle(identifier:"com.example.frameworkID")!.path(forResource: "properties", ofType: "plist")!
Swift 5: How to read variables in plist files?
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
name
Tiger
picture
tiger_running
name
Jaguar
picture
jaguar_sleeping
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. The NSDictionary/NSArray
API is objective-c-ish and outdated.
How to Read Plist without using NSDictionary in Swift?
The native Swift way is to use PropertyListSerialization
if let url = Bundle.main.url(forResource:"Config", withExtension: "plist") {
do {
let data = try Data(contentsOf:url)
let swiftDictionary = try PropertyListSerialization.propertyList(from: data, format: nil) as! [String:Any]
// do something with the dictionary
} catch {
print(error)
}
}
You can also use NSDictionary(contentsOf:
with a type cast:
if let url = Bundle.main.url(forResource:"Config", withExtension: "plist"),
let myDict = NSDictionary(contentsOf: url) as? [String:Any] {
print(myDict)
}
but you explicitly wrote: without using NSDictionary(contentsOf...
Basically don't use NSDictionary
without casting in Swift, you are throwing away the important type information.
Meanwhile (Swift 4+) there is still more comfortable PropertyListDecoder
which is able to decode Plist directly into a model.
Reading a PLIST file Dict of Dict
Try setting the format of the dictionary explicitly if you are only working with a nested dictionary that is of type [String:String]:
let dataFromPlist = try PropertyListSerialization.propertyList(from: data, format: nil) as! [String : [String : String ] ]
Based on your sample data, I created a property list whose source file converts to this in xml:
Name
Age
Two
Height
Short
The output is as you would like:
["Name": ["Height": "Short", "Age": "Two"]]
The full example code with an Example.plist file in the root of the project:
let urlPath = Bundle.main.url(forResource: "Example", withExtension: "plist")
if let urlPath = urlPath {
do {
let data = try Data(contentsOf: urlPath)
let dataFromPlist = try PropertyListSerialization.propertyList(from: data, format: nil) as! [String : [String : String ] ]
print(dataFromPlist)
} catch {
print(error)
}
}
}
How do I get content of a plist file in swift?
You can use the function url(forResource:withExtension:)
instead of the path. You can use this function (replace MyPlistFile.plist with the name of your file):
// Provide the key of the entry you need to read
func getStringValueFromPlist(forKey key: String) -> String {
guard let fileURL = url(forResource: "MyPlistFile.plist", withExtension: nil) else {
fatalError("Can't find \(fileName)")
}
let contents = NSDictionary(contentsOf: fileURL) as? [String: String] ?? [:]
return contents[key] ?? ""
}
To get a nested dictionary, you need to change the type, from String
to a dictionary type, like [String: String]
, then read inside that dictionary.
Swift 4: Adding dictionaries to Plist
NSKeyedUnarchiver
is the wrong way to save property lists.
There is a dedicated struct PropertyListSerialization
to load and save property lists.
First declare a computed property plistURL
var plistURL : URL {
let documentDirectoryURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
return documentDirectoryURL.appendingPathComponent("dictionary.plist")
}
and two methods for loading and saving
func savePropertyList(_ plist: Any) throws
{
let plistData = try PropertyListSerialization.data(fromPropertyList: plist, format: .xml, options: 0)
try plistData.write(to: plistURL)
}
func loadPropertyList() throws -> [String:String]
{
let data = try Data(contentsOf: plistURL)
guard let plist = try PropertyListSerialization.propertyList(from: data, format: nil) as? [String:String] else {
return [:]
}
return plist
}
Create the dictionary and save it
do {
let dictionary = ["key1" : "value1", "key2":"value2", "key3":"value3"]
try savePropertyList(dictionary)
} catch {
print(error)
}
To update a value read it, update the value and save it back
do {
var dictionary = try loadPropertyList()
dictionary.updateValue("value4", forKey: "key4")
try savePropertyList(dictionary)
} catch {
print(error)
}
How to add Dictionary to Plist in SWIFT
You need to convert Dictionary to NSDictionary
so that you can use writeToFile
Try to cast with this
let succeed = (favoriteGooglelocations as NSDictionary).writeToFile(path, atomically: true)
If succeed is false,check your GoogleItems class,it should conforms to NSCoding
Update,this is the code I test,you may refer to it
import UIKit
import CoreLocation
Set you GoogleItems
conforms to NSCoding
class GoogleItems: NSObject,NSCoding {
override init() {}
var name:String?
var address:String?
var distance : String?
var googleLocation: CLLocation?
var isStar : Bool?
required init(coder aDecoder: NSCoder) {
self.name = aDecoder.decodeObjectForKey("name") as? String
self.address = aDecoder.decodeObjectForKey("address") as? String
self.distance = aDecoder.decodeObjectForKey("distance") as? String
self.googleLocation = aDecoder.decodeObjectForKey("googleLocation") as? CLLocation
self.isStar = aDecoder.decodeObjectForKey("isStar") as? Bool
}
func encodeWithCoder(aCoder: NSCoder) {
if name != nil{ aCoder.encodeObject(name, forKey: "name")}
if address != nil{ aCoder.encodeObject(address, forKey: "address")}
if distance != nil { aCoder.encodeObject(distance, forKey: "distance")}
if googleLocation != nil { aCoder.encodeObject(googleLocation, forKey: "googleLocation")}
if isStar != nil {aCoder.encodeBool(isStar!, forKey: "isStar")}
}
}
Then write to file
var favoriteGooglelocations = [Int:GoogleItems]()
var item = GoogleItems()
item.isStar = true
item.name = "name"
item.address = "address"
item.googleLocation = nil
item.distance = "23"
favoriteGooglelocations[1] = item
let dic = favoriteGooglelocations as NSDictionary
let paths = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)
let documentDirectory = paths[0] as! String
let path = documentDirectory.stringByAppendingPathComponent("Favorites.plist")
let succeed = NSKeyedArchiver.archiveRootObject(dic, toFile: path)
println(succeed)
Read from file
let paths = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)
let documentDirectory = paths[0] as! String
let path = documentDirectory.stringByAppendingPathComponent("Favorites.plist")
let dic = NSKeyedUnarchiver.unarchiveObjectWithFile(path) as? [Int:GoogleItems]
if(dic != nil){
for (key,value) in dic!{
let item = value
println(item.name)
println(item.address)
}
}
Related Topics
Uiviewcontroller Returns Invalid Frame
Sqlite File Location Core Data
Drawing Uibezierpath on Code Generated Uiview
How to Import Own Classes from Your Own Project into a Playground
Understanding Performseguewithidentifier
How to Detect Orientation Change
Displaying Splash Screen for Longer Than Default Seconds
Remove Objects with Duplicate Properties from Swift Array
How to Create a Guid/Uuid Using Ios
Modal View Controllers - How to Display and Dismiss
iOS (Iphone, iPad, Ipodtouch) View Real-Time Console Log Terminal
Unique Values of Array in Swift
How to Add a Touch Event to a Uiview
Retrieving Carrier Name from iPhone Programmatically
Is This Possible to Apply the Alternative Icon to the iOS Application
How to Turn Page Programmatically in Uipageviewcontroller
Codesign Error: Provisioning Profile Cannot Be Found After Deleting Expired Profile