SVProgressHUD 代码乱序执行
SVProgressHUD code executes out of order
我正在使用 NextBus API 构建公交车预测应用程序,这将帮助用户获得预测时间和公交车信息。我实现了一个函数,该函数获取用户的当前位置和所选地址以及 returns 10 条公交路线的列表,这些路线可最大限度地减少旅行距离和时间。
这里是触发上述功能的@IBAction
:
@IBAction func findAWayPressed(_ sender: UIButton) {
// Hide confirm button.
confirmButton.isHidden = true
// Setup loading HUD.
let blue = UIColor(red: 153/255, green: 186/255, blue: 221/255, alpha: 1.0)
SVProgressHUD.setBackgroundColor(blue)
SVProgressHUD.setStatus("Finding a way for you...")
SVProgressHUD.setBorderColor(UIColor.black)
SVProgressHUD.show()
// Finds a list of ten bus routes that minimizes the distance from the user and their destination.
WayFinder.shared.findAWay(startCoordinate: origin!, endCoordinate: destination!)
SVProgressHUD.dismiss()
}
问题是 confirmButton.isHidden = true
和 SVProgressHUD 行似乎只在 WayFinder.shared.findAWay()
执行后才做任何事情。 HUD 会显示一小会儿,然后立即被 SVProgressHUD.dismiss()
关闭。
这是 findAWay
函数:
func findAWay(startCoordinate: CLLocationCoordinate2D, endCoordinate: CLLocationCoordinate2D) {
// Get list of bus routes from NextBus API.
getRoutes()
guard !self.routes.isEmpty else {return}
// Initialize the the lists of destination and origin stops.
closestDestinations = DistanceData(shortestDistance: 1000000, stops: [])
closestOrigins = DistanceData(shortestDistance: 1000000, stops: [])
// Fetch route info for every route in NextBus API.
var routeConfigsDownloaded: Int = 0
for route in routes {
// Counter is always one whether the request fails
// or succeeds to prevent app crash.
getRouteInfo(route: route) { (counter) in
routeConfigsDownloaded += counter
}
}
while routeConfigsDownloaded != routes.count {}
// Iterate through every stop and retrieve a list
// of 10 possible destination stops sorted by distance.
getClosestDestinations(endCoordinate: endCoordinate)
// Use destination stop routes to find stops near
// user's current location that end at destination stops.
getOriginStops(startCoordinate: startCoordinate)
// Sort routes by adding their orign distance and destination
// distance and sorting by total distance.
getFoundWays()
}
private func getRouteInfo(route: Route, completion: @escaping (Int) -> Void) {
APIWrapper.routeFetcher.fetchRouteInfo(routeTag: route.tag) { (config) in
if let config = config {
self.routeConfigs[route.tag] = config
} else {
print("Error retrieving route config for Route \(route.tag).")
}
completion(1)
}
}
为什么@IBAction
中的代码没有按顺序执行?在调用 findAWay
之前,hud 怎么会不显示在屏幕上?有什么想法吗?
因此,您需要阅读一些有关 "main thread" 及其工作原理的资料。也许 UNDERSTANDING THE IOS MAIN THREAD
基本上,您要求系统显示 HUD,然后执行,我假设是一个长 运行 和阻塞操作,然后在主线程中关闭所有 HUD。
在该方法存在之前,系统不可能显示 HUD,因为它将成为下一个循环的一部分(paint/layout/other 重要内容)。在这种情况下,我会倾向于某种 "promise" API,例如 PromiseKit or Hydra,因为它会大大简化希望的线程。
基本意图是 - 在主线程上显示 HUD,使用后台线程执行查询,完成后关闭 HUD,但在主线程上执行。
可能看起来像这样..
SVProgressHUD.show()
DispatchQueue.global(qos: .userInitiated).async {
WayFinder.shared.findAWay(startCoordinate: origin!, endCoordinate: destination!)
DispatchQueue.main.async {
SVProgressHUD.dismiss()
}
}
记住,永远不要在主线程上下文之外修改 UI,如果 OS 检测到这种情况,它会使您的应用程序崩溃!
我可能还会考虑使用 DispatchSemaphore
而不是 "wild running" while-loop
,所以不是..
// Fetch route info for every route in NextBus API.
var routeConfigsDownloaded: Int = 0
for route in routes {
// Counter is always one whether the request fails
// or succeeds to prevent app crash.
getRouteInfo(route: route) { (counter) in
routeConfigsDownloaded += counter
}
}
while routeConfigsDownloaded != routes.count {}
您可以使用类似...
let semaphore = DispatchSemaphore(value: routes.count)
// Fetch route info for every route in NextBus API.
var routeConfigsDownloaded: Int = 0
for route in routes {
// Counter is always one whether the request fails
// or succeeds to prevent app crash.
getRouteInfo(route: route) { (counter) in
semaphore.signal()
}
}
semaphore.wait()
这将做同样的事情,但效率更高
我正在使用 NextBus API 构建公交车预测应用程序,这将帮助用户获得预测时间和公交车信息。我实现了一个函数,该函数获取用户的当前位置和所选地址以及 returns 10 条公交路线的列表,这些路线可最大限度地减少旅行距离和时间。
这里是触发上述功能的@IBAction
:
@IBAction func findAWayPressed(_ sender: UIButton) {
// Hide confirm button.
confirmButton.isHidden = true
// Setup loading HUD.
let blue = UIColor(red: 153/255, green: 186/255, blue: 221/255, alpha: 1.0)
SVProgressHUD.setBackgroundColor(blue)
SVProgressHUD.setStatus("Finding a way for you...")
SVProgressHUD.setBorderColor(UIColor.black)
SVProgressHUD.show()
// Finds a list of ten bus routes that minimizes the distance from the user and their destination.
WayFinder.shared.findAWay(startCoordinate: origin!, endCoordinate: destination!)
SVProgressHUD.dismiss()
}
问题是 confirmButton.isHidden = true
和 SVProgressHUD 行似乎只在 WayFinder.shared.findAWay()
执行后才做任何事情。 HUD 会显示一小会儿,然后立即被 SVProgressHUD.dismiss()
关闭。
这是 findAWay
函数:
func findAWay(startCoordinate: CLLocationCoordinate2D, endCoordinate: CLLocationCoordinate2D) {
// Get list of bus routes from NextBus API.
getRoutes()
guard !self.routes.isEmpty else {return}
// Initialize the the lists of destination and origin stops.
closestDestinations = DistanceData(shortestDistance: 1000000, stops: [])
closestOrigins = DistanceData(shortestDistance: 1000000, stops: [])
// Fetch route info for every route in NextBus API.
var routeConfigsDownloaded: Int = 0
for route in routes {
// Counter is always one whether the request fails
// or succeeds to prevent app crash.
getRouteInfo(route: route) { (counter) in
routeConfigsDownloaded += counter
}
}
while routeConfigsDownloaded != routes.count {}
// Iterate through every stop and retrieve a list
// of 10 possible destination stops sorted by distance.
getClosestDestinations(endCoordinate: endCoordinate)
// Use destination stop routes to find stops near
// user's current location that end at destination stops.
getOriginStops(startCoordinate: startCoordinate)
// Sort routes by adding their orign distance and destination
// distance and sorting by total distance.
getFoundWays()
}
private func getRouteInfo(route: Route, completion: @escaping (Int) -> Void) {
APIWrapper.routeFetcher.fetchRouteInfo(routeTag: route.tag) { (config) in
if let config = config {
self.routeConfigs[route.tag] = config
} else {
print("Error retrieving route config for Route \(route.tag).")
}
completion(1)
}
}
为什么@IBAction
中的代码没有按顺序执行?在调用 findAWay
之前,hud 怎么会不显示在屏幕上?有什么想法吗?
因此,您需要阅读一些有关 "main thread" 及其工作原理的资料。也许 UNDERSTANDING THE IOS MAIN THREAD
基本上,您要求系统显示 HUD,然后执行,我假设是一个长 运行 和阻塞操作,然后在主线程中关闭所有 HUD。
在该方法存在之前,系统不可能显示 HUD,因为它将成为下一个循环的一部分(paint/layout/other 重要内容)。在这种情况下,我会倾向于某种 "promise" API,例如 PromiseKit or Hydra,因为它会大大简化希望的线程。
基本意图是 - 在主线程上显示 HUD,使用后台线程执行查询,完成后关闭 HUD,但在主线程上执行。
可能看起来像这样..
SVProgressHUD.show()
DispatchQueue.global(qos: .userInitiated).async {
WayFinder.shared.findAWay(startCoordinate: origin!, endCoordinate: destination!)
DispatchQueue.main.async {
SVProgressHUD.dismiss()
}
}
记住,永远不要在主线程上下文之外修改 UI,如果 OS 检测到这种情况,它会使您的应用程序崩溃!
我可能还会考虑使用 DispatchSemaphore
而不是 "wild running" while-loop
,所以不是..
// Fetch route info for every route in NextBus API.
var routeConfigsDownloaded: Int = 0
for route in routes {
// Counter is always one whether the request fails
// or succeeds to prevent app crash.
getRouteInfo(route: route) { (counter) in
routeConfigsDownloaded += counter
}
}
while routeConfigsDownloaded != routes.count {}
您可以使用类似...
let semaphore = DispatchSemaphore(value: routes.count)
// Fetch route info for every route in NextBus API.
var routeConfigsDownloaded: Int = 0
for route in routes {
// Counter is always one whether the request fails
// or succeeds to prevent app crash.
getRouteInfo(route: route) { (counter) in
semaphore.signal()
}
}
semaphore.wait()
这将做同样的事情,但效率更高