我有几个标签和一张地图。 在此视图中,我显示了一些有关地理位置点的信息:
加载视图后,我需要进行一些计算来更新标签。 这个计算需要几秒钟(我需要调用一个API),所以我把它们放在一个队列中:
dispatch_async(dispatch_get_main_queue(), {
let loc = CLLocationCoordinate2D(latitude: self.place!.location.latitude, longitude: self.place!.location.longitude)
let tmp = Int(Geo.apiCall(self.currentPosition, coordTo: loc));
self.label1.text = " = \(tmp) unit";
})
我使用了主线程dispatch_get_main_queue()
,因为我需要更新标签。
问题在于它阻止了地图的渲染,并且还阻止了从地理位置点收集地址的CLGeocoder
的其他异步函数。
let loc = CLLocation(latitude: self.place!.location.latitude, longitude: self.place!.location.longitude)
CLGeocoder().reverseGeocodeLocation(loc, completionHandler:
{(placemarks, error) in
if error != nil {
println("reverse geodcode fail: \(error.localizedDescription)")
}
let pms = placemarks as [CLPlacemark]
if pms.count > 0 {
let pm = placemarks[0] as CLPlacemark
self.address.text = ABCreateStringWithAddressDictionary(pm.addressDictionary, false)
}
})
因此视图显示正确,但所有标签在显示视图后几秒钟同时更新,并且仅在呈现标签时才加载地图。
在渲染视图时避免这种阻塞的最佳方法是什么?
答案 0 :(得分:3)
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT) {
//Background Thread
let loc = CLLocationCoordinate2D(latitude: self.place!.location.latitude, longitude: self.place!.location.longitude)
let tmp = Int(Geo.apiCall(self.currentPosition, coordTo: loc));
dispatch_async(dispatch_get_main_queue()) {
//Run UI Updates
self.label1.text = " = \(tmp) unit";
}
}
获取后台线程来完成不直接涉及更改ui的工作,然后在需要时调用主队列。信用到:Understanding dispatch_async
编辑:另一种选择是使用AFNetworking(用于objective-c)Alamofire(用于swift),它将异步调用你的api,你可以在完成处理程序中更改标签:https://github.com/AFNetworking/AFNetworking,tutorial:{ {3}}
EDIT-2:我没有注意并将目标C调用与你的快速声明混合在一起:P
答案 1 :(得分:0)
你应该将计算代码移动到后台队列,在主队列中设置值,这样就可以改变这样的代码:
__block let loc = CLLocationCoordinate2D(latitude: self.place!.location.latitude, longitude: self.place!.location.longitude)
__block let tmp = Int(Geo.apiCall(self.currentPosition, coordTo: loc));
dispatch_async(dispatch_get_main_queue(), {
self.label1.text = " = \(distForYou) unit";
})