Reputation: 1338
Im trying to populate a table with rows that show distances to locations from the users current location from an Array of coordinates. I have the coordinates in an empty array and I have the users location.
Im stuck on the getting the coordinates array into a function to calculate the distance, and then putting each distance value into a label in table rows. Any insight is greatly appreciated.
var locationArray: [CLLocationCoordinate2D] = []
var shopperLocation = String()
var distanceText: [String] = []
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let userLocation:CLLocation = locations[0]
shopperLocation = userLocation
self.manager.stopUpdatingLocation()
}
//This is the function I am trying to use to get distance from the array of coordinates //
func distanceToLocation(){
if locationArray == nil {
locationArray = userLocation
}
let distanceBetween: CLLocationDistance = shopperLocation.distanceFromLocation(startLocation) / 1609.34
let distanceInMilesFromUser = String(format: "%.2f", distanceBetween)
distanceText = "\(distanceInMilesFromUser) mi"
}
// Here I am trying to get the distance values in the correct rows //
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! listViewCell
cell.myDistance.text = distanceText[indexPath.row]
return cell
}
Upvotes: 2
Views: 1357
Reputation: 967
This is because you have to explicitly tell the table view to reload the data, that is to ask again its TableViewDataSource
to configure every cell with fresh data.
You can easily do so by calling tableView.reloadData()
in your CLLocationManager
's delegate method. The code below is one way to achieve that. By the way, a few remarks:
I find it more elegant to initialise Arrays using var myArray = [Type]()
than providing an explicit type and then assigning an empty array
You better save your shops parameters (name, coordinates, etc.) in a struct
Keep track of the current user location instead of the distance; doing so will enable you to easily add new shops without requesting the user location once again
Use MKDistanceFormatter
to get a nice human-readable text output for your distances — this is very powerful and will adapt to your user's locale and preferred unit system for free!
Do not forget to import all required modules:
import UIKit
import CoreLocation
import MapKit
Define your constants:
let locationCellIdentifier = "LocationCell"
and your struct:
struct Shop {
let name: String
let coordinates: CLLocation
}
And then your view controller:
final class LocationTableView: UITableViewController, CLLocationManagerDelegate {
var shops = [Shop]()
var userLocation: CLLocation?
let distanceFormatter = MKDistanceFormatter()
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
// Save the location and reloads table view
if !locations.isEmpty {
userLocation = locations.first
manager.stopUpdatingLocation()
tableView.reloadData()
}
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return shops.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(locationCellIdentifier, forIndexPath: indexPath)
// Configure the cell
let shop = shops[indexPath.row]
cell.textLabel?.text = shop.name
if let userLocation = userLocation {
let distance = shop.coordinates.distanceFromLocation(userLocation)
let formattedDistance = distanceFormatter.stringFromDistance(distance)
cell.detailTextLabel?.text = formattedDistance
} else {
cell.detailTextLabel?.text = nil
}
return cell
}
}
Upvotes: 3
Reputation: 16748
This seems kind of rough right now, so I will try to just give an outline based on what it seems like you are trying to do and the problem you seem to be having.
First you have a locationArray, but it's empty, I assume you will populate it some how.
You also have a distanceText array, so here is a suggested way you could go. (and none of this has been tested or verified so treat it more as psudeo code).
When your location is updated
ask the tableView to reload it's data.
var locationArray: [CLLocationCoordinate2D] = []
var distanceText: [String] = []
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let userLocation = locations.last
distanceText = locationArray.map { location in
// add your code to calculated the distance and return it
let distanceAsText = ....... // some function of location and userLocation
return distanceAsText
}
tableView?.reloadData()
}
Upvotes: 1