iOS 8 Swift Read Plist

iOS 8 Swift Read Plist

You may be looking for something like this:

let path = NSBundle.mainBundle().pathForResource("savedState", ofType: "plist")
let dict = NSDictionary(contentsOfFile: path!)
let players = dict.valueForKey("players") as? String
let level = dict.valueForKey("level") as? String
let numPlayers = players != nil ? players!.toInt() : 0
let playLevel = level != nil ? level!.toInt() : 0

It attempts to read players and level from the plist as optional strings, then if they are non nil it sets numPlayers and playLevel to their Int value. If they are nil numPlayers and playLevel are set to 0. Although if your plist values are integers, why not just read them as Ints?

let players = dict.valueForKey("players") as? Int
let level = dict.valueForKey("level") as? Int

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.

How can I read data from a PLIST in Swift?

First, your Root object in the plist is an NSArray not a NSDictionary.

Second, if you want to use KVC on Foundation Collections (I don't believe this works with Swift's Array) you need to call valueForKeyPath.

let chapterPath = NSBundle.mainBundle().pathForResource("chapterMapping", ofType: "plist")
if let arrayOfItems: [AnyObject] = NSArray(contentsOfFile: chapterPath!) {
let chapterNames: [String] = arrayOfItems.valueForKeyPath("chapterName") as NSArray as [String]
let pageNumbers: [Int] = arrayOfItems.valueForKeyPath("pageNumber") as NSArray as [Int]
}

Third, the swift-y way of doing this would be with the map function, but arrayOfItems would need to be a strongly-defined type and it might be more work than it's worth. Example:

let array: [ChapterMetaData] = // define it here
let chapterImages = array.map { $0.chapterImage }

How can I read Plist in Swift?

Your method signature clearly states that it returns an [Any] (i.e., Swift native Array containing elements of any type whatsoever), while you try to cast the return value into NSArray (even though it already is by virtue of intialization: NSArray(contentsOfFile:)).

Change it to:

return arry as? [Any] 
// (will return nil if the cast fails - not a problem if you
// also apply the fix mentioned below...)

The other path tries to return nil; for that to be acceptable, your signature needs to be defined as returning an optional:

func loadPlistArray() -> [Any]  // WRONG

func loadPlistArray() -> [Any]? // RIGHT

EDIT: If your app is structured in such a way that you can't afford to return nil from your method, you can instead return an empty array on failure:

else {
return [] // Empty array
}

(use [:] for empty dictionary)


Also, try to avoid using ! whenever possible, and switch to ? instead, unless you are 100% sure that whatever it is you are forcing will not fail and cause a runtime error (crash).

Read plist in swift 3 playground

To finally get the program working I used.

devices = NSArray(contentsOfFile: path) as! [AnyObject]

The issue with playground continuously running was solved by going to activity monitor and force quitting the process named com.apple.coresimulator which was identified as not responding. After doing this the playground ran instantly.

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.

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.

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)

<?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. The NSDictionary/NSArray API is objective-c-ish and outdated.



Related Topics



Leave a reply



Submit