This is in Swift 3
I am receiving an array of "segments" as JSON.
I am trying to map my data in a array of an object.
It seems that I am doing it wrong. I am getting the same amount in "duration" in every element of the array, which it's not.
I am not sure if it is the way I am running it through a loop, or what the problem is. Can anyone plz help?
Thanks a lot!
if let segmentsArray = resultData["Segments"] as? [[String: AnyObject]] {
var segments = [Segment]()
for segment in segmentsArray {
if let duration = segment["Duration"] as? NSInteger {
if let key = segment["Key"] as? String {
if let legIndexes = segment["LegIndexes"] as? NSArray {
if let stops = segment["Stops"] as? NSInteger {
let thisSegment = Segment.init(duration: duration, key: key, legIndexes: legIndexes as! [NSInteger], stops:stops)
segments.append(thisSegment)
}
}
}
}
}
Related
In this I am getting data from server response after posting parameters and here I need to display it on table view and it should be displayed like shown below in the image 0 is the price for the particular shipping method
already i had written model class for server response data and here it is
struct ShippingMethod {
let carrierCode : String
let priceInclTax : Int
let priceExclTax : Int
let available : Any
let carrierTitle : String
let baseAmount : Int
let methodTitle : String
let amount : Int
let methodCode : String
let errorMessage : Any
init(dict : [String:Any]) {
self.carrierCode = dict["carrier_code"] as! String
self.priceInclTax = dict["price_incl_tax"]! as! Int
self.priceExclTax = dict["price_excl_tax"]! as! Int
self.available = dict["available"]!
self.carrierTitle = dict["carrier_title"] as! String
self.baseAmount = dict["base_amount"]! as! Int
self.methodTitle = dict["method_title"]! as! String
self.amount = dict["amount"]! as! Int
self.methodCode = dict["method_code"] as! String
self.errorMessage = (dict["error_message"] != nil)
}
}
by using this I had formed an array type like this by using code
var finalDict = [String: [String]]()
var responseData = [ShippingMethod]()
do
{
let array = try JSONSerialization.jsonObject(with: data, options: []) as? [[String : Any]]
for item in array! {
self.responseData.append(ShippingMethod.init(dict: item))
}
print(self.responseData)
}
catch let error
{
print("json error:", error)
}
print(self.responseData)
for item in self.responseData {
let dict = item
let carrierTitle = dict.carrierTitle
let methodTitle = dict.methodTitle
if self.finalDict[carrierTitle] == nil {
self.finalDict[carrierTitle] = [String]()
}
self.finalDict[carrierTitle]!.append(methodTitle)
}
print(self.finalDict)
the output of this finalDict is ["Flat Rate": ["Fixed"], "Best Way": ["Table Rate"]] in this carrier title key value pair should be displayed as section title and is Flat Rate and method title key value pair should be displayed as rows in section Fixed but the problem is I need amount key value pair with it also for corresponding method title can anyone help me how to get this ?
Why don't you create another struct for displaying row data:
struct CarrierInfo {
let name:String
let amount:Int
}
Change your finalDict to
var finalDict = [String: [CarrierInfo]]()
and create CarrierInfo instance and set it in finalDict
for item in self.responseData {
let dict = item
let carrierTitle = dict.carrierTitle
let methodTitle = dict.methodTitle
let amount = dict.amount
if self.finalDict[carrierTitle] == nil {
self.finalDict[carrierTitle] = [CarrierInfo]()
}
self.finalDict[carrierTitle]!.append(CarrierInfo(name: carrierTitle, amount: amount))
}
Likewise you can make other required changes. This would neatly wrap your row display data inside a structure.
PS: I have not tested the code in IDE so it may contain typos.
You can assign another dictionary with key as methodTitle and amount as value. i.e., ["fixed":"whatever_amount"]
OR
You can use finalDict differently, like ["Flat Rate": ["tilte":"Fixed","amount":"0"], "Best Way": ["title":"Table Rate","amount":"0"]]
If it is difficult for you to code this, you can revert back.
Edit
You can use the following code to create the array in the second solution I suggested above:
for item in self.responseData {
let dict = item
let carrierTitle = dict.carrierTitle
let methodTitle = dict.methodTitle
let amount = dict.amount
if self.finalDict[carrierTitle] == nil {
self.finalDict[carrierTitle] = [[String:String]]()
}
let innerDict = ["title":methodTitle,"amount":amount]
self.finalDict[carrierTitle]!.append(innerDict)
}
I am completely new to swift and firebase, and I am having difficulties in retrieving array-elements from firebase database
So this is my firebase database
I can retrieve the other elements like this:
database reference
class ViewController: UIViewController {
var ref: FIRDatabaseReference?
let fileName : String = "jsonFile"
method
func parseFirebaseResponse() {
ref?.child("Vandreture").child(fileName).observe(.value, with:
{ (snapshot) in
let dict = snapshot.value as? [String: AnyObject]
let navn = dict!["navn"] as? String
print(navn as Any)
let type = dict!["type"] as? String
print(type as Any)
let Længde = dict!["length"] as? String
print(Længde as Any)
let link = dict!["link"] as? String
print(link as Any)
})
}
the console shows the result
But I have searched for a way to retrieve longitude/latitude pairs,
The first pair should be
latitude 109.987
longitude 102.987
- but so far without luck - help would really be appreciated :)
I think you should restructure your database to something like this:
Vandreture {
jsonFile {
length: "16.2"
link: "www.second.com"
navn: "Kagerup rundt"
positions {
-KqXukxnw3mL38oPeI4y {
x: "102.987"
y: "109.987"
}
-KqXukxnw3mL38oPeI5- {
x: "108.234"
y: "99.098"
}
}
}
}
Then getting your coordinates would be far easier!
Get your "position" as a dictionary (aka [String: AnyObject]).
Then get array of latitude and longitude. Then map of each element from latitude and longitude into a tuple or something like that.
guard let position = dict!["position"] as? [String: AnyObject],
let latitudeArray = position["latitude"] as? [String],
let longitudeArray = position["longitude"] as? [String] else { return }
print(latitudeArray)
print(longitudeArray)
thanks Victor Apeland - now I changed the structure of the database. I was not able to do it exactly as you suggested!!
I concatenated the lon/lat as a string (not the best - i know - I'm a newbie to swift, and firebase is not well documented)
to retrieve the individual elements from my long/lat, I used this method, and I was particular interested in the first reading, so I made a list, populated it, and got the first element, parsing it to a new method
func responsePosition() {
var positions = [String]()
ref?.child("Vandreture").child(fileName).child("position").observe(.value, with: { (snapshot) in
for snap in snapshot.children {
let userSnap = snap as! FIRDataSnapshot
let uid = userSnap.key //the uid of each user
let userDict = userSnap.value as! String
positions.append(userDict)
}
let pos : String = positions[0]
self.formatPositions(pos : pos)
})
}
In my firebase lon-lat was divided by a space, so I split the string and cast to double.
func formatPositions(pos : String) {
let lotLangDivided = pos.components(separatedBy: " ")
let longitude = Double(lotLangDivided[0])
let latitude = Double(lotLangDivided[1])
}
now I got the result i wanted
- thanks for the help Victor and Khuong :)
Hi I am currently learning Swift 3, and I have an app I am "developing" to provide weather for a specific location.
I have got my MetOffice API and retrieved the JSON required. I am able to retrieve the location without issue, but when I try to get the temp data I get no result. The temp data is listed as DM in the JSON and is an array within an array within a dictionary within dictionary.
my current code looks like
if let SiteRep = dict["SiteRep"] as? Dictionary<String, Any> {
if let DV = SiteRep["DV"] as? Dictionary<String,Any> {
if let location = DV["Location"] as? Dictionary<String, Any> {
if let period = location["Period"] as? Dictionary<String, Any> {
if let Rep = period["Rep"] as? [Dictionary<String, Any>] {
if let DM = Rep[0]["DM"] as? Double {
self._currentTemp = DM
} } } } } }
relevant vars are declared above this.
I'm not sure how to correct this code to pull this required value back from the JSON
Json as follows, the value i am trying to retrieve is highlighted in bold
{
"SiteRep":{
"Wx":{ },
"DV":{
"dataDate":"2017-02-10T12:00:00Z",
"type":"Forecast",
"Location":{
"i":"350497",
"lat":"99.6115",
"lon":"-21.0017",
"name":"TOWN",
"country":"ENGLAND",
"continent":"EUROPE",
"elevation":"160.0",
"Period":[
{
"type":"Day",
"value":"2017-02-10Z",
"Rep":[
{
"D":"NE",
"Gn":"16",
"Hn":"77",
"PPd":"51",
"S":"9",
"V":"GO",
**"Dm":"2",**
"FDm":"-2",
"W":"24",
"U":"1",
"$":"Day"
},
{
"D":"NNW",
"Gm":"20",
"Hm":"89",
"PPn":"58",
"S":"11",
"V":"GO",
"Nm":"-1",
"FNm":"-6",
"W":"24",
"$":"Night"
}
I have an application that is using the Foursquare API to download JSON data. I am using NSURLSession and the dataTaskWithRequest with completion block method to fetch the data. I am getting the data fine but sometimes a nested array named groups can be empty. And when I am parsing through the JSON like below, for some reason my conditional statement is not handling the empty array like I am expecting it should. Instead of evaluating the array as empty and proceeding to the "else" portion of the if let...else statement if instead throughs a runtime error stating: index 0 beyond bounds of empty array
if let response: NSDictionary = data["response"] as? [String: AnyObject],
groups: NSArray = response["groups"] as? NSArray,
// Error here \|/ (sometimes groups array is empty)
dic: NSDictionary = groups[0] as? NSDictionary,
items: NSArray = dic["items"] as! NSArray {
}
else {
// Never gets here. Why?
// IF the groups array is empty, then the if let should return
// false and drop down to the else block, right?
}
I am relatively new to Swift, can someone tell me why this is happening and what I can do to fix this? Thanks
You have to check explicitly outside an if letstatement if the array is empty, because
An empty array is never an optional
if let response = data["response"] as? [String: AnyObject], groups = response["groups"] as? NSArray {
if !groups.isEmpty {
if let dic = groups[0] as? NSDictionary {
items = dic["items"] as! NSArray
// do something with items
println(items)
}
}
} else ...
You can omit all type annotations while downcasting a type
However, you can perform the check with a where clause, this works in Swift 1.2 and 2
if let response = data["response"] as? [String: AnyObject],
groups = response["groups"] as? [AnyObject] where !groups.isEmpty,
let dic = groups[0] as? NSDictionary,
items = dic["items"] as? NSArray {
// do something with items
println(items)
} else {...
Use && operator between statments.
For example this won't crash:
var a = 4;
var c = 5;
var array = Array<Int>();
if a > 2 && c > 10 && array[0] != 0 {
}
Make sure the array is not empty before trying to access it:
if let response: NSDictionary = data["response"] as? [String: AnyObject],
let groups: NSArray = response["groups"] as? NSArray where groups.count > 0 {
if let dic: NSDictionary = groups[0] as? NSDictionary,
let items: NSArray = dic["items"] as? NSArray {
// Do something..
return // When the 2nd if fails, we never hit the else clause
}
}
// Do logic for else here
...
Hi I am new to Swift and Firebase here and I am trying to append the objects I get into the array I have created. But when I return the array, it returns nil even when I print the array it shows the values are stored inside.I tried to assign it to another array but it still returns nil. Please help me as I am currently a newbie to Swift and Firebase and need some guidance. Thanks in advance.
func retrieveData() -> Array<AnyObject>{
var ref = Firebase(url: "my_firebase_url")
ref.queryOrderedByChild("datetime").observeEventType(.Value, withBlock: {
snapshot in
if let i = snapshot.value as? NSDictionary {
for item in i {
if let value = item.value as? NSDictionary {
self.adArray.append(value)
println(self.adArray[0])
println(self.adArray.count)
self.codeNum = value["code"] as! String
self.datetime = value["datetime"] as! String
self.nameEvent = value["name"] as! String
println("code is \(self.codeNum) and name is \(self.nameEvent) at \(self.datetime)")
}
}
}
})
println(adArray.count)
return adArray }