uitableview - How to use Asychronous task inside for loop in swift -
i using google map in project. calculating place distance current location nd showing tableview. there multiple places , want show in tableview. each place , distance current location need call google distancematrix api. able store places cordinate inside array , looping through array calling distance martix api.
here code
func calculatedistance(type : string) { let currentlocationcordinate = "\(usercurrentlocation.coordinate.latitude),\(usercurrentlocation.coordinate.longitude)" var url = string() var remoteurl = nsurl() var request = nsurlrequest() var session = nsurlsession() var locatioarrayindex = 0 //locationarray stores cordinate of nearby array locatioarrayindex in 0...locationarray.count-1 { placecordinationarray = "\(locationarray[locatioarrayindex].coordinate.latitude),\(locationarray[locatioarrayindex].coordinate.longitude)" url = "https://maps.googleapis.com/maps/api/distancematrix/json?units=imperial&origins=\(currentlocationcordinate)&destinations=\(placecordinationarray)&key=\(key)" remoteurl = nsurl(string: url)! request = nsurlrequest(url: remoteurl) let config1 = nsurlsessionconfiguration.defaultsessionconfiguration() session = nsurlsession(configuration: config1) // asych start here let task = session.datataskwithrequest(request, completionhandler: {(data, response, error) in // convert server json response nsdictionary { let convertedjsonintodict = try nsjsonserialization.jsonobjectwithdata(data!, options: []) let rows = convertedjsonintodict["rows"] as! nsarray let elements = rows[0] let element1 = elements["elements"] as! nsarray let distance = element1[0] let distancedictionary = distance["distance"] let testdistance = distancedictionary!!["text"] as! string! self.distancemeter = testdistance self.placedistantarray.append(self.distancemeter) if (locatioarrayindex == 9) { dispatch_async(dispatch_get_main_queue(), { self.seguecheck = true self.searchactivityindicator.stopanimating() self.searchactivityindicator.hideswhenstopped = true self.tableview.reloaddata() }) } // print("location array indexinside",locatioarrayindex) } catch let error nserror { print("some error ",error.localizeddescription) } }) task.resume() }// loop closed }
i storing distance in self.placedistantarray array. , after reloading tableview data. values in self.placedistantarray reapeting sometimes. , tableview sometime array index error
you code very unclean , not readable @ all, cleaned it:
func calculatedistanceupdatingui(type : string) { //locationarray stores cordinate of nearby array (index, location) in locationarray.enumerate() { if let remoteurl = distancecalculationurlfrom(usercurrentlocation, todestination: location) { let request = nsurlrequest(url: remoteurl) let session = nsurlsession(configuration: nsurlsessionconfiguration.defaultsessionconfiguration()) // clear array self.placedistantarray.removeall() // request distance let task = session.datataskwithrequest(request, completionhandler: {(data, response, error) in { if let distancemeter = try self.testdistancefrom(data) { self.distancemeter = distancemeter self.placedistantarray.append(distancemeter) } if (index == 9) { self.updateui() } print("location array indexinside", index) } catch let error nserror { print("some error ", error.localizeddescription) } }) task.resume() } } } private func updateui() { dispatch_async(dispatch_get_main_queue()) { self.seguecheck = true self.searchactivityindicator.stopanimating() self.searchactivityindicator.hideswhenstopped = true self.tableview.reloaddata() } } private func distancecalculationurlfrom(origin: cllocation, todestination destination: cllocation) -> nsurl? { var urlstring = "https://maps.googleapis.com/maps/api/distancematrix/json?units=imperial&origins=" urlstring += "\(origin.coordinate.latitude),\(origin.coordinate.longitude)&destinations=" urlstring += "\(destination.coordinate.latitude),\(destination.coordinate.longitude)&key=\(key)" return nsurl(string: urlstring) } private func testdistancefrom(data: nsdata?) throws -> string? { guard let data = data else { return nil } let convertedjsonintodict = try nsjsonserialization.jsonobjectwithdata(data, options: []) if let rows = convertedjsonintodict["rows"] as? nsarray rows.count > 0, let element1 = rows[0]["elements"] as? nsarray element1.count > 0, let distancedictionary = element1[0]["distance"] as? nsdictionary, let testdistance = distancedictionary["text"] as? string { return testdistance } return nil }
here goes advice:
- you should not use forced unwrapping lightly.
- you should try avoid using old style loops, try use fast enumeration (more readable).
- your functions should not have side effects. if call function
calculatedistance
should that, calculate distance. not change variables suchplacecordinationarray
or update ui. - you should try split code , make smaller functions. if have add comments
// loop closed
it's large - you should not initialise object won't using (as in
var request = nsurlrequest()
) - try use correct words, such
coordinate
instead ofcordination
orlocation
instead oflocatio
.
as @jigar tarsariya said, cleaned array before filled again.
Comments
Post a Comment