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.
Related
Ok I have read so much about NSArray NSDictionary I'm lost now, what I want is to print the value 'name' from the first array item of my custom plist.
This is my plist:
and this is my code in my ViewController.swift:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let path = Bundle.main.path(forResource: "test", ofType: "plist")
let dic = NSArray(contentsOfFile: path!)
print(dic?.firstObject)
}
}
in my console I see:
Optional({
active = 0;
name = "John Doe";
})
I would think that print(dic?.firstObject["name"]) would do the trick
but I get an error: Value of type 'Any?' has no subscripts
So how do I print the values of name and active of my first array?
I know there are lots of answers on SO regarding this question, that's the reason I got so far.
but I just don't know how to fix this.
Kind regards,
Ralph
First of all please never use the NSArray/NSDictionary related API in Swift to read a property list. You are throwing away the type information.
However you can read the values with
let array = NSArray(contentsOfFile: path!) as! [[String:Any]]
for item in array {
let name = item["name"] as! String
let active = item["active"] as! Bool
print(name, active)
}
The dedicated and recommended API is PropertyListSerialization :
let url = Bundle.main.url(forResource: "test", withExtension: "plist")!
let data = try! Data(contentsOf: url)
let array = try! PropertyListSerialization.propertyList(from: data, format: nil) as! [[String:Any]]
A better way is the Codable protocol and PropertyListDecoder
struct User : Decodable {
let name : String
let active : Bool
}
override func viewDidLoad() {
super.viewDidLoad()
let url = Bundle.main.url(forResource: "test", withExtension: "plist")!
let data = try! Data(contentsOf: url)
let array = try! PropertyListDecoder().decode([User].self, from: data)
for item in array {
print(item.name, item.active)
}
}
The code must not crash. If it does you made a design mistake
To use subscripts you first need to cast the object returned by
dic?firstObject
to a dictionary, you can also unwrap the optional at this point.
if let item = dic?firstObject as? [String: Any] {
print(item["name")
}
I'm trying to access a value I've stored inside of Info.plist and the second line root = NSDictionary... fails.
I can however do this to open my other file, Common.plist.
if let path = Bundle.main.path(forResource: "Info", ofType: "plist"),
let root = NSDictionary(contentsOfFile: path) as? [String: String] {
Why am I having issues opening Info.plist?
Info.plist is not [String:String]. It can include any property list compliant type.
But there is a pretty convenient shortcut
let root = Bundle.main.infoDictionary
which returns [String:Any]
The contents of your Info.plist file are not only String:String values, but also String:Number, etc. so String:AnyObject should work.
Take a look at your Info.plist. There are all kinds of things stored in there - not just String. If you change to let root = NSDictionary(contentsOfFile: path) as? [String: Any] you will start passing that check.
You can fetch like this:
func fetchData(){
if let path = Bundle.main.path(forResource: "YourPlistName", ofType: "plist") {
if let dicObj = NSDictionary(contentsOfFile: path) as? [String: Any] {
}
}
}
I have been working hard to read plist files to my iOS app, but every method I have used so far has failed. I am currently using the method described at http://basememara.com/reading-values-plist-bundle-swift/, but in every method I have tried seems to have the same problem.
If this is the code that read the plist file:
/**
Gets the contents of the specified plist file.
- parameter plistName: property list where defaults are declared
- parameter bundle: bundle where defaults reside
- returns: dictionary of values
*/
public static func contentsOfFile(plistName: String, bundle: Bundle? = nil) -> [String : AnyObject] {
let fileParts = plistName.components(separatedBy: ".")
guard fileParts.count == 2,
let resourcePath = (bundle ?? Bundle.main).path(forResource: fileParts[0], ofType: fileParts[1]),
let contents = NSDictionary(contentsOfFile: resourcePath) as? [String : AnyObject]
let contentsarray = NSArray(contentsOfFile: resourcePath)
else { return [:] }
return contents
}
and the call is
let values = Bundle.contentsOfFile(plistName: "Event.plist")
print(values["Item0"]) // My string value 1.
With the plist looking like
the variable Contents and ContentsArray (for testing) is empty of anything. I have verified the resourcePath is correct, and there are no errors given, so I don't know what is wrong. Every other method has the correct path, but never fills the content variable.
if let path = Bundle.main.path(forResource: "Test", ofType: "plist") {
let myDict = NSDictionary(contentsOfFile: path)
print(myDict)
}
Another way -
if let url = Bundle.main.url(forResource:"Test", withExtension: "plist"),
let myDict = NSDictionary(contentsOf: url) as? [String:Any] {
print(myDict)
}
Also it might have something to do target with target membership as well. Select plist file in your project navigator and check Target Membership section of File inpector.
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'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!)