i'm facing a problem with reading data from a plist file using swift
my code:
let Chapterpath = NSBundle.mainBundle().pathForResource("chapterMapping", ofType: "plist")
let dict2 = NSDictionary(contentsOfFile: Chapterpath!)
let chaptername = dict2?.objectForKey("chapterName")
let chapterNumber = dict2?.objectForKey("pageNumber")
next i'm trying to add plist data to an array, should i simply use
var myArray = [chapterName]
my question: is the code above correct?
or im i missing something
and when i tried to print plist data using println((chapterName))
i got an error
thank you
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 }
As you say you have an array with multiple element. objectForKey does not search the hall tree levels and gets you the first one with the name. you have multiple values a loop must be envolved. Try the following:
var Chapterpath:NSString = NSBundle.mainBundle().pathForResource("chapterMapping", ofType: "plist");
var chapters:NSArray = NSArray(contentsOfFile: Chapterpath);
for chapter in chapters {
let chaptername = chapter["chapterName"]
let chapterNumber = chapter["pageNumber"]
println(chaptername);
}
Use following code to read Plist data to NSArray:
let path = NSBundle.mainBundle().pathForResource(plistName, ofType: "plist")
var list = NSArray(contentsOfFile: path!) as [[String:String]]
Simplest way to parse the AppConfig.plist file in project:
var dictionaryObj: NSDictionary?
if let filePath = NSBundle.mainBundle().pathForResource("AppConfig", ofType: "plist")
{
dictionaryObj = NSDictionary(contentsOfFile: filePath)
}
if let dict = dictionaryObj
{
//parse it as NSDictionary
}
else
{
//dictionaryObj is nil or doesn't contain anything.
}
You can use NSArray if Plist Root is Array:
let path = NSBundle.mainBundle().pathForResource("OrderHelper", ofType: "plist")
let myArray = NSArray(contentsOfFile: path!)
You can use NSDictionary if Plist Root is Dictionary:
let path = NSBundle.mainBundle().pathForResource("OrderHelper", ofType: "plist") {
let myDict = NSDictionary(contentsOfFile: path!)
Related
Swift 3
I'm trying to read a plist file to update my array for collection view.
My menu.plist has 6 items that I want to read and append to my array that uses .count to update the collection view.
Problem is I'm having trouble sorting the dictionary. I want to append the strings in value to my array but sort the transfer by the key which has the text "Item 0", "Item 1", etc. Because the array comes unorganized which makes it harder to use the switch statements on didSelectItemAt.
In the code I'm not using key only appending value to mainGroup array but its unorganized and I need to filter it by the plist key
Code in ViewDidLoad
var mainGroup = [String]()
var myDict: NSDictionary?
if let path = Bundle.main.path(forResource: "menu", ofType: "plist") {
myDict = NSDictionary(contentsOfFile: path)
}
if let dict = myDict {
print(dict)
for (_, value) in dict {
mainGroup.append("\(value)")
}
print(mainGroup)
}
Plist
You need sort your dict.keys array and the access to value by those sorted keys
Full code
var mainGroup = [String]()
var myDict: [String:String]?
if let path = Bundle.main.path(forResource: "menu", ofType: "plist") {
myDict = NSDictionary(contentsOfFile: path) as? [String:String]
}
if let dict = myDict {
print(dict)
for key in dict.keys.sorted() {
mainGroup.append(dict[key]!)
}
print(mainGroup)
}
update
Using array as #rmaddy says
var mainGroup = [String]()
var myArray: [String]?
if let path = Bundle.main.path(forResource: "menu", ofType: "plist") {
myArray = NSArray(contentsOfFile: path) as? [String]
}
print(myArray)
This is from a property list I created:
I want to load just the country names into an array. Here's the code I have so far...
if let path = Bundle.main.path(forResource: "flagData", ofType: "plist") {
dict = NSMutableDictionary(contentsOfFile: path)
let currentGroup = (dict!["caribbean"] as AnyObject).allKeys as? [String]
}
But that doesn't work - when I run it, currentGroup = nil
I also tried:
let currentGroup = dict?.allKeys(for: "caribbean")
But that gives me an empty array.
Any ideas will be appreciated... Thanks!
if let path = Bundle.main.path(forResource: "flagData", ofType: "plist"),
let configurations = NSDictionary(contentsOfFile: path) {
variables = configurations[currentConfiguration] as! NSDictionary
}
Try the above code and make relevant changes i think error in your code is while you cast its failing.
How I remove Plist repeated values in Swift?
if let bundlePath = Bundle.main.path(forResource: "Places", ofType: "plist") {
if let dicionario = NSDictionary(contentsOfFile: bundlePath) {
places = dicionario["places"] as? NSArray
//places = Array(Set(places))
tableView.reloadData()
}
}
I've tried to use places = Array(Set(places)) but I have an error
Can I convert NSArray to Array?
I have created a simple dictionary:
let quotes: NSArray = ["hello", "ola", "hi"]
Then I randomly access the strings in this dictionary with the following code:
let range: UInt32 = UInt32(quotes.count)
let randomNumber = Int(arc4random_uniform(range))
let QuoteString = quotes.objectAtIndex(randomNumber)
self.resultLabel.text = QuoteString as? String
Since I would ultimately like aloft of items in my dictionary, I should create a .plist file and called it "Quotes.plist" - it will be easier to manage a dictionary of many strings.
How can I write a simple code so as to randomly access strings within my .plist?
Amended Code:
func randomWord() -> String? {
guard let
path = NSBundle.mainBundle().pathForResource("Quotes", ofType: "plist"),
words = NSDictionary(contentsOfFile: path) as? [String:String] else { return nil }
let randomIndex = Int(arc4random_uniform(UInt32(words.values.count)))
return Array(words.values)[randomIndex]
My .plist file is "Quotes.plist".
A simple question (I apologise in advance), but how do I modify self.resultLabel.text = QuoteString as? String so that the random quote now appears in my resultLabel.txt?
IF your PLIST is defined as a Dictionary then this should do the job. Otherwise please provide mode details about how your PLIST is structured.
func randomWord() -> String? {
guard let
path = NSBundle.mainBundle().pathForResource("Words", ofType: "plist"),
words = NSDictionary(contentsOfFile: path) as? [String:String] else { return nil }
let randomIndex = Int(arc4random_uniform(UInt32(words.values.count)))
return Array(words.values)[randomIndex]
}
I have a plist file ("myAwayList.plist") to store navigation data. I have nested a Dictionary of String variables in an Array in the main Dictionary as follows..
<dict>
<key>Locations</key>
<array>
<dict>
<key>Name</key>
<string>Sydney City Centre</string>
<key>Address</key>
<string>Centrepoint Tower</string>
<key>Lat</key>
<string>-33.870451</string>
<key>Lon</key>
<string>151.208771</string>
</dict> ...
I can successfully load and use the array data inside with the following...
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) as NSArray
let documentsDirectory = paths.objectAtIndex(0)as NSString
let path = documentsDirectory.stringByAppendingPathComponent("myAwayList.plist")
let fileManager = NSFileManager.defaultManager()
// Check if file exists
if(!fileManager.fileExistsAtPath(path))
{
// If it doesn't, copy it from the default file in the Resources folder
let bundle = NSBundle.mainBundle().pathForResource("myAwayList", ofType: "plist")
fileManager.copyItemAtPath(bundle!, toPath: path, error:nil)
println("File did not exist! Default copied...")
}
let dict = NSDictionary(contentsOfFile: path)!
let mySavedLocations: AnyObject = dict.objectForKey("Locations")!
println("plist all: \(mySavedLocations)")
if let nsArray:NSArray = mySavedLocations as? NSArray{
for var loadCount = 0; loadCount < mySavedLocations.count; ++loadCount {
var locationDict:AnyObject = nsArray[loadCount] // loading array data at index
let arrayName = locationDict["Name"] as AnyObject? as String
let arrayAddress = locationDict["Address"] as AnyObject? as String
let arrayLat = locationDict["Lat"] as AnyObject? as String
let arrayLon = locationDict["Lon"] as AnyObject? as String
awaydatalist.append(AwayData(name:arrayName, address:arrayAddress, lat:arrayLat, lon:arrayLon)) // This is a list array used to display the loaded data on a ViewController
}
}
I now want to append the array inside with another row of data, and write back to the plist file, but I cannot find a way to do it. Please advise?
Chris
Here is the code to add new Dictionary inside the array stored in plist file
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) as NSArray
let documentsDirectory = paths.objectAtIndex(0)as NSString
let path = documentsDirectory.stringByAppendingPathComponent("myAwayList.plist")
let fileManager = NSFileManager.defaultManager()
// Check if file exists
if(!fileManager.fileExistsAtPath(path))
{
// If it doesn't, copy it from the default file in the Resources folder
let bundle = NSBundle.mainBundle().pathForResource("myAwayList", ofType: "plist")
fileManager.copyItemAtPath(bundle!, toPath: path, error:nil)
println("File did not exist! Default copied...")
}
let dict = NSMutableDictionary(contentsOfFile: path)!
let mySavedLocations: AnyObject = dict.objectForKey("Locations")!
println("plist all: \(mySavedLocations)")
if let nsArray:NSArray = mySavedLocations as? NSArray
{
for var loadCount = 0; loadCount < mySavedLocations.count; ++loadCount
{
var locationDict:AnyObject = nsArray[loadCount] // loading array data at index
let arrayName = locationDict["Name"] as AnyObject? as String
let arrayAddress = locationDict["Address"] as AnyObject? as String
let arrayLat = locationDict["Lat"] as AnyObject? as String
let arrayLon = locationDict["Lon"] as AnyObject? as String
// awaydatalist.append(AwayData(name:arrayName, address:arrayAddress, lat:arrayLat, lon:arrayLon)) // This is a list array used to display the loaded data on a ViewController
}
}
//Convert AnyObject to NSMutableArray
var twDataArray = (mySavedLocations as NSMutableArray) as NSMutableArray
//Create a new Dictionary
let airports: [String: String] = ["Name": "Toronto Pearson", "Address": "Dublin","Lat":"23.23","Lon":"78.89"]
//add dictionary to array
twDataArray.addObject(airports)
//set the new array for location key
dict.setObject(mySavedLocations, forKey: "Locations")
//update the plist
dict.writeToFile(path, atomically: true)
This code add a new dictionary inside the location array.