1 前言
如果想要在 GCD 的幫助下能夠異步執行 Non-UI 相關任務。在主隊列、串行隊列和並發隊列上異步執行代碼塊才能見識到 GCD 的真正實力。
要在分派隊列上執行異步任務,你必須使用下面這些函數中的其中一個:
dispatch_async
為了異步執行向分派隊列提交一個 Block Object(2 個都通過函數指定);
eg:dispatch_sync(concurrentQueue, printFrom1To1000);
dispatch_async_f
為了異步執行向分派隊列提交一個 C 函數和一個上下文引用(3 項通過函數指定) 。
eg:dispatch_sync_f(concurrentQueue,NULL,printFrom1To1000);
2 代碼實例
這節代碼有點多,所以分了兩個工程
First:ZYViewController.m
[plain] - (void) viewDidAppear:(BOOL)paramAnimated{
//新建一個隊列
dispatch_queue_t concurrentQueue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//執行concurrentQueue隊列
dispatch_async(concurrentQueue, ^{
__block UIImage *image = nil;
dispatch_sync(concurrentQueue, ^{
/*下載圖片*/
/* 聲明圖片的路徑*/
NSString *urlAsString = @"http://up.2cto.com/2013/0519/20130519101223949.jpg";
//轉換為NSURL對象
NSURL *url = [NSURL URLWithString:urlAsString]; NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
//聲明NSError對象:一個NSError對象封裝錯誤信息更豐富、更具可擴展性可以只使用一個錯誤代碼和錯誤字符串。
NSError *downloadError = nil;
//獲得對應的Url返回的數據(這裡是一個圖片的數據)
NSData *imageData = [NSURLConnection
sendSynchronousRequest:urlRequest returningResponse:nil error:&downloadError];
if (downloadError == nil &&imageData != nil){
//將NSData轉換為圖片
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.");
}
});
dispatch_sync(dispatch_get_main_queue(), ^{
/* 在主線程裡面顯示圖片*/
if (image != nil){
/* 穿件UIImageView視圖 */
UIImageView *imageView = [[UIImageView alloc]
initWithFrame:self.view.bounds];
/* 設置Image */
[imageView setImage:image];
/* 內容適應視圖的大小通過保持長寬比*/
[imageView setContentMode:UIViewContentModeScaleAspectFit];
/* 想Controller View添加圖像視圖 */
[self.view addSubview:imageView];
} else {
NSLog(@"Image isn't downloaded. Nothing to display.");
} });
});
}
- (void) viewDidAppear:(BOOL)paramAnimated{
//新建一個隊列
dispatch_queue_t concurrentQueue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//執行concurrentQueue隊列
dispatch_async(concurrentQueue, ^{
__block UIImage *image = nil;
dispatch_sync(concurrentQueue, ^{
/*下載圖片*/
/* 聲明圖片的路徑*/
NSString *urlAsString = @"http://up.2cto.com/2013/0519/20130519101223949.jpg";
//轉換為NSURL對象
NSURL *url = [NSURL URLWithString:urlAsString]; NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
//聲明NSError對象:一個NSError對象封裝錯誤信息更豐富、更具可擴展性可以只使用一個錯誤代碼和錯誤字符串。
NSError *downloadError = nil;
//獲得對應的Url返回的數據(這裡是一個圖片的數據)
NSData *imageData = [NSURLConnection
sendSynchronousRequest:urlRequest returningResponse:nil error:&downloadError];
if (downloadError == nil &&imageData != nil){
//將NSData轉換為圖片
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.");
}
});
dispatch_sync(dispatch_get_main_queue(), ^{
/* 在主線程裡面顯示圖片*/
if (image != nil){
/* 穿件UIImageView視圖 */
UIImageView *imageView = [[UIImageView alloc]
initWithFrame:self.view.bounds];
/* 設置Image */
[imageView setImage:image];
/* 內容適應視圖的大小通過保持長寬比*/
[imageView setContentMode:UIViewContentModeScaleAspectFit];
/* 想Controller View添加圖像視圖 */
[self.view addSubview:imageView];
} else {
NSLog(@"Image isn't downloaded. Nothing to display.");
} });
});
}
運行結果
Second:
ZYViewController.h
[plain] #import <UIKit/UIKit.h>
@interface ZYViewController : UIViewController
@property(nonatomic,strong) UILabel *myLabel;
@end
#import <UIKit/UIKit.h>
@interface ZYViewController : UIViewController
@property(nonatomic,strong) UILabel *myLabel;
@end
ZYViewController.m
[plain] @synthesize myLabel;
- (void)viewDidLoad
{
[super viewDidLoad];
//聲明一個隊列
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
/*
如果我們還沒有保存1000個隨機數在磁盤上,下面的隊列就用來生成這個文件並且用一個Array存放在磁盤上
*/
dispatch_async(concurrentQueue, ^{
NSUInteger numberOfValuesRequired = 10000;
//判斷文件是否存在
if ([self hasFileAlreadyBeenCreated]== NO){
dispatch_sync(concurrentQueue, ^{
//聲明一個可變數組用來存放數值
NSMutableArray *arrayOfRandomNumbers =[[NSMutableArray alloc] initWithCapacity:numberOfValuesRequired];
NSUInteger counter = 0;
for (counter = 0;counter < numberOfValuesRequired;counter++){
//獲得隨機數
unsigned int randomNumber =arc4random() % ((unsigned int)RAND_MAX + 1);
[arrayOfRandomNumbers addObject:[NSNumber numberWithUnsignedInt:randomNumber]];
}
//將這個array寫入到磁盤上
[arrayOfRandomNumbers writeToFile:[self fileLocation] atomically:YES];
});
}
//存放讀取文件內容的數組
__block NSMutableArray *randomNumbers = nil;
//從磁盤上讀取文件並升序排列
dispatch_sync(concurrentQueue, ^{
//如果文件已經被創建,讀取他
if ([self hasFileAlreadyBeenCreated]){
randomNumbers = [[NSMutableArray alloc] initWithContentsOfFile:[self fileLocation]];
/* 排序 */
[randomNumbers sortUsingComparator:^NSComparisonResult(id obj1, id obj2)
{
NSNumber *number1 = (NSNumber *)obj1;
NSNumber *number2 = (NSNumber *)obj2;
return [number1 compare:number2];
}];
}
});
dispatch_async(dispatch_get_main_queue(), ^{
if ([randomNumbers count] > 0){
/* 刷新主線程 */
CGRect labelFrame = CGRectMake(0.0f, 0.0f, 300.0f, 200.0f);
self.myLabel = [[UILabel alloc] initWithFrame:labelFrame];
self.myLabel.numberOfLines = 10;//分10行
NSString *str = [[NSString alloc] initWithFormat:@"RandomNumbers is %@",randomNumbers];//方法一
self.myLabel.text = str;//label的文字
self.myLabel.font = [UIFont boldSystemFontOfSize:14.0f];//字體樣式
self.myLabel.center = self.view.center;//UILabel控件居中
[self.view addSubview:self.myLabel];
}
});
});
}
//獲得文件路徑
-(NSString *)fileLocation{
/*
創建一個列表的目錄搜索路徑。
NSDocumentDirectory:文檔目錄。
NSUserDomainMask:用戶的主目錄的地方,存放用戶的個人項目。
*/
NSArray *folders = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
/* 如果沒有找到返回空 */
if ([folders count] == 0)
{return nil; }
/* 獲得文件路徑的字符串形式 */
NSString *documentsFolder = [folders objectAtIndex:0];
//將文件名追加到foldser後面
return [documentsFolder stringByAppendingPathComponent:@"list.txt"];
}
//判斷文件是否被存在
- (BOOL) hasFileAlreadyBeenCreated{
BOOL result = NO;
//初始化NSFileManager文件管理對象
NSFileManager *fileManager = [[NSFileManager alloc] init];
//判斷文件是否存在
if ([fileManager fileExistsAtPath:[self fileLocation]])
{
result = YES;
}
return result;
}
@synthesize myLabel;
- (void)viewDidLoad
{
[super viewDidLoad];
//聲明一個隊列
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
/*
如果我們還沒有保存1000個隨機數在磁盤上,下面的隊列就用來生成這個文件並且用一個Array存放在磁盤上
*/
dispatch_async(concurrentQueue, ^{
NSUInteger numberOfValuesRequired = 10000;
//判斷文件是否存在
if ([self hasFileAlreadyBeenCreated]== NO){
dispatch_sync(concurrentQueue, ^{
//聲明一個可變數組用來存放數值
NSMutableArray *arrayOfRandomNumbers =[[NSMutableArray alloc] initWithCapacity:numberOfValuesRequired];
NSUInteger counter = 0;
for (counter = 0;counter < numberOfValuesRequired;counter++){
//獲得隨機數
unsigned int randomNumber =arc4random() % ((unsigned int)RAND_MAX + 1);
[arrayOfRandomNumbers addObject:[NSNumber numberWithUnsignedInt:randomNumber]];
}
//將這個array寫入到磁盤上
[arrayOfRandomNumbers writeToFile:[self fileLocation] atomically:YES];
});
}
//存放讀取文件內容的數組
__block NSMutableArray *randomNumbers = nil;
//從磁盤上讀取文件並升序排列
dispatch_sync(concurrentQueue, ^{
//如果文件已經被創建,讀取他
if ([self hasFileAlreadyBeenCreated]){
randomNumbers = [[NSMutableArray alloc] initWithContentsOfFile:[self fileLocation]];
/* 排序 */
[randomNumbers sortUsingComparator:^NSComparisonResult(id obj1, id obj2)
{
NSNumber *number1 = (NSNumber *)obj1;
NSNumber *number2 = (NSNumber *)obj2;
return [number1 compare:number2];
}];
}
});
dispatch_async(dispatch_get_main_queue(), ^{
if ([randomNumbers count] > 0){
/* 刷新主線程 */
CGRect labelFrame = CGRectMake(0.0f, 0.0f, 300.0f, 200.0f);
self.myLabel = [[UILabel alloc] initWithFrame:labelFrame];
self.myLabel.numberOfLines = 10;//分10行
NSString *str = [[NSString alloc] initWithFormat:@"RandomNumbers is %@",randomNumbers];//方法一
self.myLabel.text = str;//label的文字
self.myLabel.font = [UIFont boldSystemFontOfSize:14.0f];//字體樣式
self.myLabel.center = self.view.center;//UILabel控件居中
[self.view addSubview:self.myLabel];
}
});
});
}
//獲得文件路徑
-(NSString *)fileLocation{
/*
創建一個列表的目錄搜索路徑。
NSDocumentDirectory:文檔目錄。
NSUserDomainMask:用戶的主目錄的地方,存放用戶的個人項目。
*/
NSArray *folders = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
/* 如果沒有找到返回空 */
if ([folders count] == 0)
{return nil; }
/* 獲得文件路徑的字符串形式 */
NSString *documentsFolder = [folders objectAtIndex:0];
//將文件名追加到foldser後面
return [documentsFolder stringByAppendingPathComponent:@"list.txt"];
}
//判斷文件是否被存在
- (BOOL) hasFileAlreadyBeenCreated{
BOOL result = NO;
//初始化NSFileManager文件管理對象
NSFileManager *fileManager = [[NSFileManager alloc] init];
//判斷文件是否存在
if ([fileManager fileExistsAtPath:[self fileLocation]])
{
result = YES;
}
return result;
}
運行結果