Is there any ways to load an arrays of String into URL to be loaded in UIWebview? I am using plist to get the values. My incorrect code to retrieve the value is
if let path = Bundle.main.path(forResource: "BOITLIST", ofType: "plist") {
let dictRoot = NSDictionary(contentsOfFile: path)
if let dict = dictRoot {
let userEnteredData = dict["webURL"] as! [String]
let url = URL(string: userEnteredData)
webView.loadRequest(URLRequest(url:url!))
}
}
and my plist looks like
The menu items 1-7 are the side menus i made. I would like to show the different loads from the URL when I click on each Menu Items
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.
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.
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!)