异步执行UI无关任务
这才是GCD大显神威的地方,我保证,学完这一章节后,在以后的多线程编程中,你将深深爱上GCD
dispatch_async
提交block对象到队列以便异步执行
dispatch_async_f
提交C函数到队列,异步执行
我们来实现一个功能,从网上下载一张图片并显示出来。
代码框架是这样的
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(concurrentQueue, ^{
__block UIImage *image = nil;
dispatch_sync(concurrentQueue, ^{
/* Download the image here */
});
dispatch_sync(dispatch_get_main_queue(), ^{
/* Show the image to the user here on the main queue*/
});
});
第二个dispatch_sync将在第一个dispatch_sync执行后才执行。
看下详细例子
- (void) viewDidAppear:(BOOL)paramAnimated
{
NSLog(@"viewDidAppear");
dispatch_queue_t concurrentQueue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(concurrentQueue, ^{
NSLog(@"dispatch_async");
__block UIImage *image = nil;
dispatch_sync(concurrentQueue, ^{
NSLog(@"dispatch_sync1");
/* Download the image here */
/* iPad's image from Apple's website. Wrap it into two lines as the URL is too long to fit into one line */
NSString *urlAsString = @"http://i3.sinaimg.cn/home/2013/0331/U586P30DT20130331093840.png";
NSURL *url = [NSURL URLWithString:urlAsString];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
NSError *downloadError = nil;
NSData *imageData = [NSURLConnection
sendSynchronousRequest:urlRequest returningResponse:nil error:&downloadError];
if (downloadError == nil && imageData != nil){
image = [UIImage imageWithData:imageData]; /* We have the image. We can use it now */
}else if (downloadError != nil){
NSLog(@"Error happened = %@", downloadError);
}else {
NSLog(@"No data could get downloaded from the URL.");
}
NSLog(@"dispatch_sync1 over");
});
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"dispatch_sync2");
/* Show the image to the user here on the main queue*/
if (image != nil){
/* Create the image view here */
UIImageView *imageView = [[UIImageView alloc]
initWithFrame:self.view.bounds]; [imageView setImage:image];
/* Set the image */
/* Make sure the image is not scaled incorrectly */
[imageView setContentMode:UIViewContentModeScaleAspectFit]; /* Add the image to this view controller's view */
[self.view addSubview:imageView];
} else {
NSLog(@"Image isn't downloaded. Nothing to display.");
}
NSLog(@"dispatch_sync2 over");
});
NSLog(@"dispatch_async over");
});
NSLog(@"viewDidAppear over");
}
执行结果是
2014-03-05 17:26:56.042 cookbook6_7[699:a0b] viewDidAppear
2014-03-05 17:26:56.043 cookbook6_7[699:a0b] viewDidAppear over
2014-03-05 17:26:56.043 cookbook6_7[699:1403] dispatch_async
2014-03-05 17:26:56.043 cookbook6_7[699:1403] dispatch_sync1
2014-03-05 17:26:56.073 cookbook6_7[699:1403] dispatch_sync1 over
2014-03-05 17:26:56.073 cookbook6_7[699:a0b] dispatch_sync2
2014-03-05 17:26:56.075 cookbook6_7[699:a0b] dispatch_sync2 over
2014-03-05 17:26:56.077 cookbook6_7[699:1403] dispatch_async over
这里还有一个小小例子,
- (void) viewDidAppear:(BOOL)paramAnimated
{
NSLog(@"viewDidAppear");
dispatch_queue_t concurrentQuene =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(concurrentQuene,^{
NSLog(@"Call1");
dispatch_sync(concurrentQuene,^{
[NSThread sleepForTimeInterval:2];
NSLog(@"Call2");
});
dispatch_sync(dispatch_get_main_queue(),^{
NSLog(@"Call3");
});
});
}
由于对这套东西还不是很熟悉,我一直不明白第一个dispatch_sync有什么用,把它去掉结果也都一样,后来在网上有人告诉我说,去掉不影响结果的正确性,加上后可以有多线程的优化而已。不知事实是否如此。