patternswiftMinor
Parsing travel duration data
Viewed 0 times
traveldataparsingduration
Problem
I'm trying to parse an estimated travel duration and distance between two waypoints using Google Directions API. Tap on this to see an example of data received.
This code works fine but looks awful. What I need is do nothing if data is incorrect. I can't come anything up with it. The main goal is avoiding of getting different unwrapping errors if something is wrong. I would greatly appreciate any help.
private class func parseTravelData(
data: AnyObject!,
mode: ESTMode,
completion: (NSDictionary?) -> Void) {
var receivedData = data as? NSDictionary
if let routes = receivedData?["routes"] as? NSArray {
if routes.count > 0 {
if let legs = routes[0]["legs"] as? NSArray {
if legs.count > 0 {
var dur: String? = nil
if let duration = legs[0]["duration"] as? NSDictionary {
if let v = duration["value"] as? Float {
if v > ConnectionManager().timeMax && mode == .Walking {
completion(nil) // resend using drive mode
}
else {
if let t = duration["text"] as? String {
dur = t
}
}
}
}
if let d = dur {
if let distance = legs[0]["distance"] as? NSDictionary {
if let dist = distance["text"] as? String {
completion([
"duration": d,
"distance": dist])
}
}
}
}
}
}
}
}This code works fine but looks awful. What I need is do nothing if data is incorrect. I can't come anything up with it. The main goal is avoiding of getting different unwrapping errors if something is wrong. I would greatly appreciate any help.
Solution
Not sure if this code is correct or will compile but here is my attempt...
Here are a few things I did to try to make the code more concise
I noticed that the interesting stuff only happens if the route contains a leg. So I was able to eliminate a few if statement blocks by using optional chaining and moving code out of the if conditions and into the
Another optimization I made is that I moved the
I also renamed some variables for more clarity, for example I renamed
I was able to eliminate the
One thing I noticed that the
private class func parseTravelData(data: AnyObject!, mode: ESTMode, completion: NSDictionary? -> Void) {
let receivedData = data as? NSDictionary
let routes = receivedData?["routes"] as? NSArray
let legs = routes?.firstObject?["legs"] as? NSDictionary
if let firstLeg = legs?.firstObject as? NSDictionary {
let firstLegDurationDict = firstLeg["duration"] as? NSDictionary
let firstLegDuration = firstLegDurationDict?["value"] as? Float
if firstLegDuration > ConnectionManager().timeMax && mode == .Walking {
completion(nil) // resend using drive mode
} else if let durationStr = firstLegDurationDict?["text"] as? String {
let distanceDict = firstLeg["distance"] as? NSDictionary
if let distanceStr = distanceDict?["text"] as? String {
completion(["duration": durationStr, "distance": distanceStr])
}
}
}
}Here are a few things I did to try to make the code more concise
I noticed that the interesting stuff only happens if the route contains a leg. So I was able to eliminate a few if statement blocks by using optional chaining and moving code out of the if conditions and into the
receivedData, routes, and legs variables. (The individual variables are not strictly necessary but make the code more readable). So the first "if let" check happens to see if there is actually a leg in the optional legs array.Another optimization I made is that I moved the
if let d = dur block into the else statement above since the code will only proceed if duration["text"] exists. This also allowed me to eliminate the var dur: String? = nil statement as well.I also renamed some variables for more clarity, for example I renamed
v to firstLegDuration.I was able to eliminate the
if let v block since if v (which is now firstLegDuration) is nil then v > ConnectionManager().timeMax will be false since nil > AnyObject == false.One thing I noticed that the
completion does not get called in all cases, which to me seems weird, so if there is an error or missing data then nothing will happen.Code Snippets
private class func parseTravelData(data: AnyObject!, mode: ESTMode, completion: NSDictionary? -> Void) {
let receivedData = data as? NSDictionary
let routes = receivedData?["routes"] as? NSArray
let legs = routes?.firstObject?["legs"] as? NSDictionary
if let firstLeg = legs?.firstObject as? NSDictionary {
let firstLegDurationDict = firstLeg["duration"] as? NSDictionary
let firstLegDuration = firstLegDurationDict?["value"] as? Float
if firstLegDuration > ConnectionManager().timeMax && mode == .Walking {
completion(nil) // resend using drive mode
} else if let durationStr = firstLegDurationDict?["text"] as? String {
let distanceDict = firstLeg["distance"] as? NSDictionary
if let distanceStr = distanceDict?["text"] as? String {
completion(["duration": durationStr, "distance": distanceStr])
}
}
}
}Context
StackExchange Code Review Q#77940, answer score: 2
Revisions (0)
No revisions yet.