Reading keys in plist and get the values - ios

I have the following plist file in my Swift iOS project. I want to read the keys without specifically mention and get the value for all the keys. I want to write this in Swift code. I tried the below code and getting all the keys and values. But, I want to check for each key(not mentioned specifically like "1234" etc.) and get the value for it. Please help how to achieve this?
var myDict: NSDictionary?
if let path = NSBundle.mainBundle().pathForResource("UserDetails", ofType: "plist") {
myDict = NSDictionary(contentsOfFile: path)
NSLog("myDict: %#", myDict!)
}

Just use this code
for (key, val) in myDict! {
println("\(key):\(val)")
}
to print the single keys/values.

You can use a tuple to loop in a dictionary:
for (key, value) in myDict! {
println("Key is \(key) and value is \(value)")
}

Related

How to access a variable using its name as a string

I was thinking of using a plist file to configure how I would upload a form to my server but then I realised I don't know how I could do one crucial part of this or even if this is possible since you can't dynamically declare variables with swift.
Basically I was thinking of using a dictionary like this
form:
property_name: backend_name
and then in my form upload method I would do something that would look like this
formValues: [String:String] = [:]
form.forEach { (property_name, backend_name) in
let value = someController[property_name] // to do the equivalent of someController.property_name
formValues[backend_name] = value
}
// ...
formValues.forEach { (backend_name, value) in
multipartFormData.append(value.data(using: String.Encoding.utf8)!, withName: backend_name)
}
the problem is I don't know how to this part
let value = someController[property_name]
The problem you're trying to solve is serializing your data for a server. I don't know whether the approach you're trying is possible in Swift, but it's definitely not the right one. If you're using Swift 4, you could create Codable model objects, so this serialization will be all under the hood. Otherwise, you'll most likely need to create this [String: Any] manually.
Using Codable to serialize/deserialize objects
I found how I could do it.
formValues: [String:String] = [:]
form.forEach { (property_name, backend_name) in
let value = Mirror(reflecting: someController).children.filter({ (child) -> Bool in
return child.label == property_name
}).first!.value as! String
formValues[backend_name] = value
}
// ...
formValues.forEach { (backend_name, value) in
multipartFormData.append(value.data(using: String.Encoding.utf8)!, withName: backend_name)
}
I know this is unoptimised since I recreate a mirror each cycle but it's for demonstration purposes

Swift 3: Array Value for key

New to swift, just trying to catch some data.
so here is my swift code i used
let url = Bundle.main.url(forResource: "kurdiebg", withExtension: "plist")!
do {
let data = try Data(contentsOf: url)
let dataArray = try PropertyListSerialization.propertyList(from: data, format: nil) as! [[String:String]]
// Bloody Error is this
let request = dataArray(value(forKey: "Key"))
print(dataArray.count)
} catch {
print("This error must not happen", error)
}
i am getting
Cannot call value of non-function type '[[String : String]]'
what exactly i am trying to do?
so i have this plist file and i want to allow users to search in it , i perform this via a button action with this code above, so if a user write abbey, it would get the kurdi meaning,
The error occurs because you are using wrong syntax.
dataArray is not a function, you probably mean
dataArray.value(forKey: "Key")
However using KVC methods like value(forKey is only useful if you know what KVC is and why you need KVC. In this case it's inappropriate.
dataArray – as the name implies – is an array which is subscripted by index so you can get for example the value for key english of the first item with
dataArray[0]["english"]
which is a synonym for
dataArray[0].object(forKey:"english")
Or if you want to find an item for a specific key
dataArray.first(where: { $0["english"] == "abbey"})

Swift NSDictionary get 0th value without knowing key name

I have an NSDictionary that has a key like messageID5 and the value has three key/value pairs.
I know the NSDictionary only has 1 value in it because I limited my query to 1. But I don't know the name of the key. I just want the value, but I can't access it like an array [0]. You can access it just fine in PHP or Python. I've been trying a lot of different solutions for this basic problem, but a lot of them seem overly messy. anyValue[0] gives me a type error.
If you don't know your dictionary keys, you can get your NSDictionary allKeys.first property or allValues.first:
let dict = NSDictionary(dictionary: ["a":["b":1]])
let subDict = dict[dict.allKeys.first] as? [String:Any] ?? [:] // ["b": 1]
// or
let subDict = dict.allValues.first as? [String:Any] ?? [:] // ["b": 1]
The first thing to acknowledge is that key/value pairs in dictionaries does not maintain any specific order - this is required for an optimization in access to the contents of this structure.
As for your case if you're 100% sure you'll have only one value inside your dictionary you can use .allValues.first to retrieve the contained value. If your know that the type of your value is NSDictionary the whole code may look like this:
let childDictionary = rootDictionary.allValues.first as? NSDictionary
I suggest using (dictionary as Dictionary).values.first. That returns an optional, since it can fail if the dictionary is empty.
(Note that I edited this answer to cast the dictionary from an NSDictionary to a Dictionary so you an use the values property. NSDictionary doesn't have a values property, but Dictionary does.)

iOS 9 JSON Parsing loop

I'm creating an app that should retrieve some JSON from a database.
This is how my JSON looks:
[{"id":"1","longitude":"10","latitude":"10","visibility":"5","timestampAdded":"2015-10-01 15:01:39"},{"id":"2","longitude":"15","latitude":"15","visibility":"5","timestampAdded":"2015-10-01 15:06:25"}]
And this is the code i use:
if let jsonResult = JSON as? Array<Dictionary<String,String>> {
let longitudeValue = jsonResult[0]["longitude"]
let latitudeValue = jsonResult[0]["latitude"]
let visibilityValue = jsonResult[0]["visibility"]
print(longitudeValue!)
print(latitudeValue!)
print(visibilityValue!)
}
As you can see it only gets the first chunk from the JSON and if there are no JSON at all it will crash, but if i want it to count the amount and make an array out of it like this:
var longitudeArray = [10, 15]
var latitudeArray = [10, 15]
And so on...
I also need this to be apple watch compatible so i can't use SwiftyJSON.
What do i do? I really hope you can help me!
Thanks.
SOLVED!
Problems was solved by "Eric D."
This is the code:
do {
if let url = NSURL(string: "YOU URL HERE"),
let data = NSData(contentsOfURL: url),
let jsonResult = try NSJSONSerialization.JSONObjectWithData(data, options: []) as? [[String:AnyObject]] {
print(jsonResult)
let longitudeArray = jsonResult.flatMap { $0["longitude"] as? String }
let latitudeArray = jsonResult.flatMap { $0["latitude"] as? String }
print(longitudeArray)
print(latitudeArray)
}
} catch let error as NSError {
print(error.description)
}
Thank you soo much Eric!! :-)
You could use flatMap to get an array of your elements:
let longitudeArray = jsonResult.flatMap { $0["longitude"] as? String }
let latitudeArray = jsonResult.flatMap { $0["latitude"] as? String }
etc.
flatMap is like map but unwraps optionals, which is adequate because we need to safely cast the type of the object we get from each dictionary in the json array.
$0 represents the object in the current iteration of flatMap of the array it's applied to.
If you're currently using SwiftyJSON, then that would be:
let longitudeArray = jsonResult.flatMap { $1["longitude"].string }
let latitudeArray = jsonResult.flatMap { $1["latitude"].string }
because .string is SwiftyJSON's optional String value getter.
But as you said, you don't want to use it (anymore), so you need to use NSJSONSerialization to decode your JSON data, there's plenty of examples on the Web and on SO. Then you will be able to use my original answer.
You're already getting an array with all of the elements (not just the first one. you're simply only accessing the first one). jsonResult is an array of dictionaries. Each dictionary (in this case, based on the json you provided) contains these elements: id, longitude, latitude, visibility and timestampAdded. In order to access each of them, you can simply loop over jsonResult and access the i'th element (and not always the 0 element). This will also prevent the crash you're experiencing with the json is blank or invalid (since you'll only be going over the valid elements in jsonResult.
This will give you the flexibility to create the custom arrays you wish to create (in order to create an array of all of the longitudes, for example, you will simply add that element to the new array while looping over jsonResult). However, if you'd like to save yourself the trouble of manually building these arrays and assuming you have control over the json structure, I would recommend changing the received json to the relevant structure (a dictionary or arrays instead of an array of dictionaries), so it would better fit your needs and provide you the results in the relevant format right "out of the box".

using key : value after loading dictionary from a plist using swift

I'm using Xcode 6 with Swift.
When I create a dictionary programmatically, I can print out by key or value or create arrays. When I create and load a dictionary from a plist, I can print the plist in total, but can't create arrays or print either the keys or values. The error message is 'NSDictionary?' does not have a member named 'values'.
I notice the programmatic dictionary is printed inside brackets with a colon between key and value, but the plist loaded dictionary is printed inside braces with = signs between the key and value. I assume this may be the problem, but don't know why it formatted this way or how to fix it.
// Programmatic Dictionary Code
var newDict:[String:String] = ["car":"ground", "airplane":"sky", "boat":"water"]
println("newDict key:value are: \(newDict)")
//Prints Out as expected
newDict key:value are: [car: ground, boat: water, airplane: sky]
// plist read to Dictionary Code
var type : NSDictionary?
if let path = NSBundle.mainBundle().pathForResource("transport", ofType: "plist") {
type = NSDictionary(contentsOfFile:path)
}
println(type)
// print out isn't the same as above
Optional({
airplane = sky;
boat = water;
car = ground;
})
Trying to access the key or the element in this loaded dictionary returns an error message indicating the dictionary doesn't have a member ....
I've been unable to find anything to explain why the loaded dictionary would be different or how to access the members.
You need to unwrap your optionals. An optional is a variable that can hold a value just like any other variable, but it can also hold no value at all, or nil.
This code:
var type : NSDictionary?
if let path = NSBundle.mainBundle().pathForResource("transport", ofType: "plist") {
type = NSDictionary(contentsOfFile:path)
}
println(type)
should be:
var type : NSDictionary?
if let path = NSBundle.mainBundle().pathForResource("transport", ofType: "plist") {
type = NSDictionary(contentsOfFile:path)
}
println(type!)
Anytime you use type (or any other optional), you need to unwrap it with !, ?, or if let.
Note that if type contained nil and you unwrap it with !, your app will crash, saying "unexpectedly found nil while unwrapping optional value".
For more information about optionals, see The Swift Programming Language: The Basics.

Resources