问题描述
- 该查询循环遍历数据库中的学校列表以检索其坐标
- 计算距用户当前位置的距离
- 如果距离小于20英里,请使用MKDirections()计算eta时间。
- 计算出eta时间后,将相关信息附加到表格视图的数组中,按eta时间对数组进行排序,仅保留前10位
这里的问题是,在用户当前位置的20英里范围内,通常有许多机构,并且MKDirections()限制了您可以在给定时间范围内计算eta时间的请求数量。因此,很多时候我的表格视图无法显示eta时间。
对我来说,显而易见的解决方案是在计算eta时间之前对数组进行排序和修剪(从而避免出现过多的计算eta请求问题)。
我尝试过的事情:
- 将for循环内的数据追加到“ Array1”
- 排序和修剪Array1
- 在for循环之外/之后,我遍历Array1以计算eta时间,然后将此数据附加到Array2,后者将是提供表格视图的数组
我发现这是行不通的,因为在for循环完成之前执行了for循环之外/之后的代码。
let schoolDB = Database.database().reference().child("Schools")
schoolDB.observe(.value,with: { (snapshot) in
self.subjectTimesArray.removeAll()
for child in snapshot.children {
let schoolSnapshot = child as! DataSnapshot
let approvalString = schoolSnapshot.childSnapshot(forPath: "Approved").value as! String
if approvalString == "Yes" {
let schoolID = schoolSnapshot.key
let schoolName = schoolSnapshot.childSnapshot(forPath: "Name").value as! String
let schoolLatitude = schoolSnapshot.childSnapshot(forPath: "Latitude").value as! Double
let schoolLongitude = schoolSnapshot.childSnapshot(forPath: "Longitude").value as! Double
let schoolLocation = CLLocation(latitude: schoolLatitude,longitude: schoolLongitude)
let distance = schoolLocation.distance(from: self.userLocation) / 1600
if distance < 20 {
let subjectDB = Database.database().reference().child("Subject/" + schoolID + "/" + date)
subjectDB.observeSingleEvent(of: .value,with: { (subjectSnapshot) in
let startTime = subjectSnapshot.childSnapshot(forPath: "Maths/Start").value as! String
let userPlacemark = MKMapItem(placemark: MKPlacemark(coordinate: userLocation.coordinate))
let schoolPlacemark = MKMapItem(placemark: MKPlacemark(coordinate: schoolLocation.coordinate))
let directionsRequest = MKDirections.Request()
directionsRequest.source = userPlacemark
directionsRequest.destination = schoolPlacemark
directionsRequest.requestsAlternateRoutes = false
directionsRequest.transportType = .automobile
let directions = MKDirections(request: directionsRequest)
directions.calculateETA(completionHandler: { (response,error) in
if let seconds = response?.expectedTravelTime {
let minutes = seconds / 60
self.subjectTimesArray.append(.init(schoolID: schoolID,schoolName: schoolName,distance: distance,eta: Int(minutes),subjectStart: startTime))
}
self.subjectTimesArray.sort(by: {$0.eta < $1.eta})
if self.subjectTimesArray.count > 10 {
self.subjectTimesArray.removeLast(self.subjectTimesArray.count - 10)
}
self.subjectTimesTableView.reloadData()
})
})
}
}
}
})
解决方法
您可以创建一个函数,该函数使用参数作为学校的距离来计算距离,并在距离小于20英里时调用它,或者如果数据库中的学校小于20英里,则将数据库中的每个学校追加到新数组中并计算出该距离数组。如果您选择第二种方法,则只会遍历20英里以下的学校,我建议使用第一种方法。