Ios 什么';使用dispatch_async()避免视图阻塞

Ios 什么';使用dispatch_async()避免视图阻塞,ios,multithreading,swift,Ios,Multithreading,Swift,我有一个带有两个标签和一张地图的视图。 在此视图中,我将显示有关地理位置点的一些信息: 地址 地图+大头针 第一个标签(已计算) 第二个标签(已计算) 加载视图后,我需要进行一些计算以更新标签。 此计算需要几秒钟(我需要调用API),因此我将它们放入了一个队列中: dispatch_async(dispatch_get_main_queue(), { let loc = CLLocationCoordinate2D(latitude: self.place!.location.lat

我有一个带有两个标签和一张地图的视图。 在此视图中,我将显示有关地理位置点的一些信息:

  • 地址
  • 地图+大头针
  • 第一个标签(已计算)
  • 第二个标签(已计算)
加载视图后,我需要进行一些计算以更新标签。 此计算需要几秒钟(我需要调用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\u get\u main\u 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)
        }
})
因此,视图显示正确,但所有标签都会在视图显示几秒钟后同时更新,并且只有在渲染标签时才会加载贴图


在渲染视图时,避免这种阻塞的最佳解决方法是什么?

您应该将计算代码移动到后台队列,在主队列中只需设置值,就可以像这样更改代码:

__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";

})

您应该将计算代码移动到后台队列,在主队列中只需设置值,这样您就可以像这样更改代码:

__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";

})

您应该将计算代码移动到后台队列,在主队列中只需设置值,这样您就可以像这样更改代码:

__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";

})

您应该将计算代码移动到后台队列,在主队列中只需设置值,这样您就可以像这样更改代码:

__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";
})

获取一个后台线程来完成不直接涉及更改ui的工作,然后在需要时调用主队列。归功于:

编辑:另一个选项是使用AFNetworking(对于objective-c)Alamofire(对于swift),它将异步调用您的api,您可以在完成处理程序中更改标签:,教程:

编辑2:我没有注意,把目标C的电话和你的快速声明混在了一起:p

获取一个后台线程来完成不直接涉及更改ui的工作,然后在需要时调用主队列。归功于:

编辑:另一个选项是使用AFNetworking(对于objective-c)Alamofire(对于swift),它将异步调用您的api,您可以在完成处理程序中更改标签:,教程:

编辑2:我没有注意,把目标C的电话和你的快速声明混在了一起:p

获取一个后台线程来完成不直接涉及更改ui的工作,然后在需要时调用主队列。归功于:

编辑:另一个选项是使用AFNetworking(对于objective-c)Alamofire(对于swift),它将异步调用您的api,您可以在完成处理程序中更改标签:,教程:

编辑2:我没有注意,把目标C的电话和你的快速声明混在了一起:p

获取一个后台线程来完成不直接涉及更改ui的工作,然后在需要时调用主队列。归功于:

编辑:另一个选项是使用AFNetworking(对于objective-c)Alamofire(对于swift),它将异步调用您的api,您可以在完成处理程序中更改标签:,教程:


EDIT-2:我没有注意到,将objective C调用与您的swift声明混合在一起:p

使用此API执行一个工作块的目的是不在主队列上执行它。像这样在主队列上使用
dispatch\u async
完全不符合目的。使用标准的“分派到后台,分派回主”我知道,但我认为在后台队列中更新UI(标签)是不可能的?好的,我明白你的意思。我必须将任务(API调用)分派到后台队列。当任务完成时,它将被分派回主线程。你有一段代码来说明这一点吗?感谢补充答案:干净的设计需要使调用
Geo.apiCall
本身异步。使用此API执行工作块的目的是不在主队列上执行。像这样在主队列上使用
dispatch\u async
完全不符合目的。使用标准的“分派到后台,分派回主”我知道,但我认为在后台队列中更新UI(标签)是不可能的?好的,我明白你的意思。我必须将任务(API调用)分派到后台队列。当任务完成时,它将被分派回主线程。你有一段代码来说明这一点吗?感谢补充答案:干净的设计需要使调用
Geo.apiCall
本身异步。使用此API执行工作块的目的是不在主队列上执行。像这样在主队列上使用
dispatch\u async
完全不符合目的。使用标准的“分派到后台,分派回主”我知道,但我认为在后台队列中更新UI(标签)是不可能的?好的,我明白你的意思。我必须将任务(API调用)分派到后台队列。当任务完成时,它将被分派回主线程。你有一段代码来说明这一点吗?感谢补充答案:干净的设计需要使调用
Geo.apiCall
本身异步。使用此API执行工作块的目的是不在主队列上执行。像这样在主队列上使用
dispatch\u async
完全不符合目的。使用标准的“分派到后台,分派回主”我知道,但我认为在后台队列中更新UI(标签)是不可能的?好的,我明白你的意思。我必须将任务(API调用)分派到后台队列。当任务完成后,它将被分派回t