我有两个标签和一张地图。
在此视图中,我将显示有关地理位置点的一些信息:
地址
地图+大头针
第一个标签(计算)
第二个标签(计算)
加载视图后,我需要进行一些计算以更新标签。
这个计算需要几秒钟(我需要调用一个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(),因为我需要更新标签。
问题是它阻止了映射的呈现,同时也阻止了另一个异步函数从地理位置点收集地址。
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)
        }
})

因此,视图显示正确,但所有标签都会在显示视图后几秒同时更新,并且只有在呈现标签时才会加载地图。
在渲染视图时,避免这种阻塞的最佳方法是什么?

最佳答案

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,您可以在completion handler中更改标签:https://github.com/AFNetworking/AFNetworking,tutorial:http://www.raywenderlich.com/59255/afnetworking-2-0-tutorial
编辑2:我没注意,把目标C电话和你的swift声明混为一谈:P

关于ios - 如何避免使用dispatch_async()造成 View 阻塞,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26579943/

10-10 20:41
查看更多