2017-10-12 5 views
0

Je peux afficher la liste des emplacements sur une table. Mais maintenant je veux trier en fonction de l'emplacement actuel.Afficher une liste des emplacements les plus proches de l'utilisateur sur une table

Voilà comment j'afficher mes emplacements:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
    let cell = tableView.dequeueReusableCell(withIdentifier: "locationCell", for: indexPath) 

    let location = LocationManager.shared.locations[indexPath.row] 
    cell.textLabel?.text = location.name 
    return cell 
} 

J'ai essayé de mettre en œuvre cette distance dans ma classe Location que je suis arrivé de https://stackoverflow.com/a/35200027/6362735 mais je ne sais pas ce que je dois faire ensuite et comment Trier.

Voici ma classe Lieu:

class Location { 
    var name: String 
    var latitude: Double 
    var longitude: Double 
    var location:CLLocation { 
     return CLLocation(latitude: latitude, longitude: longitude) 
    } 

    init?(json: JSON) { 
     guard let name = json["name"] as? String, let latitude = json["latitude"] as? Double, let longitude = json["longitude"] as? Double else { return nil } 
     self.name = name 
     self.latitude = latitude 
     self.longitude = longitude 
    } 

    func distance(to location: CLLocation) -> CLLocationDistance { 
     return location.distance(from: self.location) 
    } 
} 

Affichage de l'emplacement actuel:

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { 
    let location = locations[0] 

    let span:MKCoordinateSpan = MKCoordinateSpanMake(0.01, 0.01) 
    let myLocation:CLLocationCoordinate2D = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude) 
    let region:MKCoordinateRegion = MKCoordinateRegionMake(myLocation, span) 
    mapView.setRegion(region, animated: true) 

    self.mapView.showsUserLocation = true 
} 

Répondre

2

Ce que vous devez faire est maintenant pour trier LocationManager.shared.locations par la distance et passer l'emplacement de votre utilisateur en tant que paramètre. Vous pouvez mettre ces deux à l'intérieur de votre LocationManager.

func getSortedLocations(userLocation: CLLocation) -> [Location] { 
    return locations.sorted { (l1, l2) -> Bool in 
     return l1.distance(to: userLocation) < l2.distance(to: userLocation) 
    } 
} 

func sortLocationsInPlace(userLocation: CLLocation) { 
    locations.sort { (l1, l2) -> Bool in 
     return l1.distance(to: userLocation) < l2.distance(to: userLocation) 
    } 
} 

Une fois que vous triez les lieux, appelez tableView.reloadData() et vos lignes doivent être commandés par la distance. L'utilisation de ce code dépend de la structure de votre application.

Si vous utilisez un bouton pour filtrer, vous pouvez trier vos emplacements dans l'action:

@IBAction func orderByDistance() { 
    sortLocationsInPlace(userLocation: yourUsersLocation) 
    tableView.reloadData() 
} 

Si vous voulez que vos données soient toujours commandé, vous pouvez trier lorsque vous créez votre tableView pour la première fois. A l'intérieur de votre UIViewController:

let sortedLocations: [Location]() 

override func viewDidLoad() { 
    sortedLocations = getSortedLocations(userLocation: yourUsersLocation) 
} 

puis vous pouvez changer votre méthode dataSource pour:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
    let cell = tableView.dequeueReusableCell(withIdentifier: "locationCell", for: indexPath) 

    let location = sortedLocations[indexPath.row] 
    cell.textLabel?.text = location.name 
    return cell 
} 

également, rappelez-vous que vous pouvez utiliser sort ou sorted selon si vous voulez sorte en place ou créer une copie triée . Pour plus d'informations sur le fonctionnement de CLLocationManager, vous devez lire here.

+0

Merci pour votre réponse. Mais pourriez-vous élaborer là où je l'appellerais sur mon application? – mninety5

+0

Cela dépend de la structure de votre application.Si vous avez un bouton ou quelque chose qui déclenche l'action de filtrage, vous devriez le mettre là. Si vous voulez que vos emplacements soient toujours triés par distance, vous pouvez le placer dans le contrôleur de TableView dans 'viewDidLoad' par exemple. Je vais mettre à jour la réponse dans les deux cas. – jvrmed

+0

Qu'est-ce que je mets dans les paramètres cependant? Quand j'utilise votre fonction de tri, il dit simplement: 'argument manquant pour le paramètre 'to' in call'. Il attend un 'CLLocation'. – mninety5

0

Utilisez votre fonction distance pour trier le tableau résultant par left < right:

locations.sorted(by: { $0.distance(to: myLocation) < $1.distance(to: myLocation) }) 

Voici un exemple de travail, vous pouvez tester avec:

import Foundation 
import CoreLocation 

struct Location { 

    var latitude: Double 
    var longitude: Double 
    var location:CLLocation { 
     return CLLocation(latitude: latitude, longitude: longitude) 
    } 

    init(lat: Double, long: Double) { 
     self.latitude = lat 
     self.longitude = long 
    } 

    func distance(to location: CLLocation) -> CLLocationDistance { 
     return location.distance(from: self.location) 
    } 
} 

let locations: [Location] = [ 
    Location(lat: 61.98573, long: 27.57300), 
    Location(lat: -62.98404, long: 62.81190), 
    Location(lat: -3.18446, long: 107.07900)] 

let myLocation = CLLocation(latitude: 73.30051, longitude: -141.88647) 

let locationsClosestToMe = locations.sorted(by: { $0.distance(to: myLocation) < $1.distance(to: myLocation) }) 

Prouver la fonction (test unitaire):

print(locationsClosestToMe.map { $0.distance(to: myLocation) }) 

/* 
[ 
    4970593.6601553941, 
    11003159.607318919, 
    18486409.053517241 
] 
*/ 
+0

Merci pour votre réponse. Je suis un peu confus comment je peux utiliser myLocation pour être l'emplacement actuel plutôt qu'un emplacement codé en dur? Mon code montre comment je reçois l'emplacement actuel. Mais c'est un 'CLLocationCoordinate2DMake' et pas un' CLLocation' comme votre méthode l'exige. Comment puis-je obtenir les données à afficher sur ma table? – mninety5

+1

Jetez un oeil à https://stackoverflow.com/a/25698536/1214800? il devrait faire ce dont vous avez besoin. De toute façon, vous initialisez le 2DMake avec les valeurs lat/long de la même manière qu'un objet 'CLLocation' standard est initialisé. – brandonscript