创建一个函数,在数组中查找基于Lat-long的最近对象



我创建了以下代码,用于获取数组中离用户位置最近的点。这不起作用。我可以找到位置,但不能找到最近的。我的目标是能够聚集最近的点并打印出项目的pm2值。

import UIKit
import CoreLocation
extension Point {
var location: CLLocation { .init(latitude: latitude ?? 5, longitude: longitude ?? 5) }
}
class popAirViewController: UITableViewController, CLLocationManagerDelegate {
private let popAirURL = "https://www.purpleair.com/json"
private var results = [Point]()
var locationManager: CLLocationManager!
var PM5Value: Int = 5
var points: [Point] = []
var destination: CLLocation?
//Temporary background image
var backgroundImage: String = "Green"
// sets PM5 text Label
@IBOutlet weak var latLabel: UILabel!
//@IBOutlet weak var latLabel: UILabel!
func PM5Text(){
latLabel.text = "56.5"
latLabel.textAlignment = .center
latLabel.numberOfLines = 10
latLabel.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height+300)
}
override func viewDidLoad() {
self.tableView.backgroundView = UIImageView(image: UIImage(named: backgroundImage))
self.tableView.backgroundColor = .clear
super.viewDidLoad()
//sets background images
if 0 ... 50 ~= Int(PM5Value) {
self.tableView.backgroundView = UIImageView(image: UIImage(named: "Green"))}
else if 51 ... 100 ~= Int(PM5Value) {
self.tableView.backgroundView = UIImageView(image: UIImage(named: "Yellow"))}
else if 101 ... 150 ~= Int(PM5Value) {
self.tableView.backgroundView = UIImageView(image: UIImage(named: "Orange"))}
else if 151 ... 1000 ~= Int(PM5Value) {
self.tableView.backgroundView = UIImageView(image: UIImage(named: "Purple"))}
print(PM5Value)
self.navigationController?.navigationBar.isHidden = true;
//let fullImageView = UIImageView(frame: self.view.frame)
//view.addSubview(fullImageView)
if (CLLocationManager.locationServicesEnabled())
{
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
locationManager.startUpdatingLocation()
}
tableView.estimatedRowHeight = 92.0
tableView.rowHeight = UITableView.automaticDimension
getLatestLocations()
}
// MARK: - Table view data source
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
PM5Text()
}
override func numberOfSections(in tableView: UITableView) -> Int {
// Return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// Return the number of rows
return results.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! KivaLoanTableViewCell
// Configure the cell...
cell.amountLabel.text = results[indexPath.row].pm2
return cell
}
// MARK: - Helper methods
func getLatestLocations() {
guard let pointUrl = URL(string: popAirURL) else {
return
}
let request = URLRequest(url: pointUrl)
let task = URLSession.shared.dataTask(with: request, completionHandler: { (data, response, error) -> Void in
if let error = error {
print(error)
return
}
// Parse JSON data
if let data = data {
self.results = self.parseJsonData(data: data)
// Reload table view
OperationQueue.main.addOperation({
self.tableView.reloadData()
})
}
})
task.resume()
}
func parseJsonData(data: Data) -> [Point] {
var points = [Point]()
do {
let jsonResult = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers) as? NSDictionary
// Parse JSON data
let jsonPoints = jsonResult?["results"] as! [AnyObject] as [AnyObject]
for jsonPoint in jsonPoints {
var point = Point()
point.latitude = jsonPoint["Lat"] as? Double
point.longitude = jsonPoint["Lon"] as? Double
point.pm2 = jsonPoint["PM2_5Value"] as? String
let latq = point.latitude
let lonq = point.longitude
//let destination = CLLocationCoordinate2DMake(latq ?? 5, lonq ?? 5)
self.destination = CLLocation(latitude: latq ?? 5, longitude: lonq ?? 5)
points.append(point)
//print(destination)
print("Destination=: (destination!)")
}
} catch {
print(error)
}
return points 
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
var userLocation:CLLocation = locations[0]
let long = userLocation.coordinate.longitude;
let lat = userLocation.coordinate.latitude;
if let closestPoint = points.min(by:{
$0.location.distance(from: userLocation) < $1.location.distance(from: userLocation)
}) {
print("closest point:", closestPoint)
}
if destination == nil{
return
}
userLocation = CLLocation(latitude: lat , longitude: long )
}
}

您可以使用CLLocationdistance(from: CLLocation)方法获得与当前位置的距离,并使用min(by: )方法获得与您的点的最小距离:

var points: [Point] = []
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations[0]
if let closestPoint = points.min(by: {
$0.location.distance(from: location) < $1.location.distance(from: location)
}) {
print("closest point:", closestPoint)
}

}

添加此助手以从您的点构建位置:

extension Point {
var location: CLLocation { .init(latitude: latitude, longitude: longitude) }
}

顺便说一句,Swift的命名惯例是以小写字母开头命名您的房产:

struct Point: Equatable {
let pm2: String
let latitude: Double
let longitude: Double
}

编辑/更新:与您的问题无关,但您应该使用Codable协议解析API的json响应:

游乐场测试:

import UIKit
import CoreLocation
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
struct Root: Codable {
let results: [Point]
}
struct Point: Codable {
let pm2: String?
let latitude, longitude: Double?
enum CodingKeys: String, CodingKey {
case pm2 = "PM2_5Value", latitude = "Lat", longitude = "Lon"
}
}
extension Point {
var location: CLLocation { .init(latitude: latitude ?? .zero, longitude: longitude ?? .zero) }
}
let popAirURL = "https://www.purpleair.com/json"
URLSession.shared.dataTask(with: URL(string: popAirURL)!) { data, response, error in
guard let data = data else {
print("error", error!)
return
}
do {
let points = try JSONDecoder().decode(Root.self, from: data).results
let location = CLLocation(latitude: 38, longitude: -121)
if let closestPoint = points.min(by: {
$0.location.distance(from: location) < $1.location.distance(from: location)
}) {
print("closest point:", closestPoint)  // closest point: Point(pm2: Optional("107.47"), latitude: Optional(38.100134), longitude: Optional(-120.860454))
}
} catch {
print(error)
}
}.resume()

最新更新