IOS开发~GCD

来源:互联网 发布:手机网络怎么重置系统 编辑:程序博客网 时间:2024/05/22 14:46


















实现代码:

CGDHelper

/* *  Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法。 *  系统要求:iOS4.0以上。 */#import <Foundation/Foundation.h> ///////////////////////////////////////     enum 声明     ///////////////////////////////////////////////////队列优先级typedef enum{    GlobalQueuePriorityDefault = 0,    GlobalQueuePriorityHigh = 2,    GlobalQueuePriorityLow = -2,    GlobalQueuePriorityBackground = INT16_MIN    } GlobalQueuePriority;//阻塞、非阻塞typedef enum{    PerformBlockFeatureChoke,    PerformBlockFeatureUnchoke    } PerformBlockFeature;//网络请求方法typedef enum GCDHelperHttpRequestMethod{    GCDHelperHttpRequestMethodGET = 0,    GCDHelperHttpRequestMethodPOST    } GCDHelperHttpRequestMethod;///////////////////////////////////////     Block 声明     ///////////////////////////////////////////////////返回值voidtypedef     void (^GCDBlock)                         (void);typedef     void (^GCDBlock1_Size_t)                 (size_t index);typedef     void (^GCDBlock1_Int)                    (int index);typedef     void (^GCDBlock1_Bool)                   (BOOL flag);typedef     void (^GCDBlock1_Float)                  (float index);typedef     void (^GCDBlock1_Obj)                    (id object);//返回值void,两个形式参数typedef     void (^GCDBlock2)                        (id object1, size_t index);typedef     void (^GCDBlock2_Obj_Int)                (id object1, int index);typedef     void (^GCDBlock2_Obj_Obj)                (id object1, id object2);//有返回值typedef     id   (^GCD_Obj_Block_Obj)                (id object);typedef     id   (^GCD_Obj_Block_Void)               (void);typedef     void (^GCDHttpRequestBlock)              (NSURLResponse *response, NSError *error, NSData *data);///////////////////////////////////////     GCDHelper 声明     /////////////////////////////////////////////////@interface GCDHelper : NSObject/* 获取3种队列 */+ (dispatch_queue_t) gcdMainQueue;+ (dispatch_queue_t) gcdGlobalQueue:(GlobalQueuePriority) priority;+ (dispatch_queue_t) gcdCustomQueue:(NSString *) queueName;//后台执行+ (void) gcdPerformBlockAsynchronous:(GCDBlock) block;//后台获取数据后,回到主线程+ (void) gcdPerformBlockAsynchronous:(GCDBlock) blockAsyn                         finishOnMainQueue:(GCDBlock) blockM;/* 3种队列上执行Block  * * 是否阻塞执行:(PerformBlockFeature) feature * 全局队列优先级:(GlobalQueuePriority) priority */+ (void) gcdPerformBlockOnMainQueue:(GCDBlock) block feature:(PerformBlockFeature) feature;+ (void) gcdPerformBlockOnGlobalQueue:(GCDBlock) block                              feature:(PerformBlockFeature) feature                             priority:(GlobalQueuePriority) priority;+ (void) gcdPerformBlockOnCustomQueue:(GCDBlock) block                              feature:(PerformBlockFeature) feature                                 name:(NSString *) queueName;//延迟执行方法+ (void) gcdPerformBlock:(GCDBlock) block                 onQueue:(dispatch_queue_t) queue             delaySecond:(int64_t) second;//只执行一次+ (void) gcdPerformBlockOnce:(GCDBlock) block;//并发+ (void) gcdBatchPerformBlocks:(NSArray *) blockArray finally:(GCDBlock) finallyBlock;+ (void) gcdBatchPerformBlockWithData:(NSArray *) dataArray          maxConcurrentOperationCount:(uint) count                          handleBlock:(GCDBlock1_Obj) block                              finally:(GCDBlock1_Obj) finallyBlock;@end///////////////////////////////////////     图片下载     /////////////////////////////////////////////////@interface GCDHelper (ImageDownload)- (void) gcdImageWithURLString:(NSString *) URLString;- (void) gcdImageWithURLString:(NSString *) URLString completion:(GCDBlock2_Obj_Obj) completion;@end///////////////////////////////////////     网络请求     /////////////////////////////////////////////////GCDBlock1_Bool _netWorkBlock;@interface GCDHelper (NetworkConnect)//网络连接判断、实时监控- (void) gcdNetWorkGuarder:(NSString *) hostname withBlock:(GCDBlock1_Bool) block;@end@interface GCDHelper (HttpRequest)//GCD请求网络(GET方式测试通过,POST方式测试未通过)- (void) gcdHttpRequestWithURL:(NSString *) URLString                    httpMethod:(GCDHelperHttpRequestMethod) method                        params:(NSDictionary *) params                       timeout:(NSTimeInterval) time                       success:(GCDHttpRequestBlock) successBlock                          fail:(GCDHttpRequestBlock) failBlock;@end



#import "GCDHelper.h"#import <SystemConfiguration/SystemConfiguration.h>#import <sys/socket.h>#import <netinet/in.h>#import <netinet6/in6.h>#import <arpa/inet.h>#import <ifaddrs.h>#import <netdb.h>//Error#define GCDHelperErrorURLISNULL   [NSError errorWithDomain:@"please setup GCDHelper‘s url or urlString" code:100 userInfo:nil]#define GCDHelperErrorRequestISNULL  [NSError errorWithDomain:@"request can not be nil!" code:101 userInfo:nil]#define GCDHelperErrorFileExist    [NSError errorWithDomain:@"File Exist!" code:102 userInfo:nil]#define GCDHelperErrorCreateFail   [NSError errorWithDomain:@"Create File Fail!" code:103 userInfo:nil]//下载的临时文件的后缀#define kTHDownLoadTask_TempSuffix  @".TempDownload"//计算下载速度的取样时间#define kTHDownLoadTimerInterval  2.0//THDispatchQueue默认的并发数#define kTHDispatchQueueDefaultConcurrentCount 10#define kDefaultTimeoutInterval  15static NSString * const BOUNDRY        = @"--------------------------7d71a819230404";@implementation GCDHelper- (void) dealloc{    [super dealloc];}- (id) init{    if (self = [super init])    {    }        return self;}#pragma mark -#pragma mark 获取队列+ (dispatch_queue_t) gcdMainQueue{    return dispatch_get_main_queue();}+ (dispatch_queue_t) gcdGlobalQueue:(GlobalQueuePriority) priority{    switch (priority)    {        case GlobalQueuePriorityDefault:            return dispatch_get_global_queue(priority, 0);            break;        case GlobalQueuePriorityHigh:            return dispatch_get_global_queue(priority, 0);            break;        case GlobalQueuePriorityLow:            return dispatch_get_global_queue(priority, 0);            break;        case GlobalQueuePriorityBackground:            return dispatch_get_global_queue(priority, 0);            break;                    default:            return dispatch_get_global_queue(GlobalQueuePriorityDefault, 0);            break;    }}+ (dispatch_queue_t) gcdCustomQueue:(NSString *) queueName;{    return dispatch_queue_create([queueName UTF8String], NULL);}#pragma mark -#pragma mark 3种队列上执行Block+ (void) gcdPerformBlockOnMainQueue:(GCDBlock) block feature:(PerformBlockFeature) feature{    switch (feature)    {        case PerformBlockFeatureChoke:            dispatch_sync([GCDHelper gcdMainQueue], block);            break;                    case PerformBlockFeatureUnchoke:            dispatch_async([GCDHelper gcdMainQueue], block);            break;                    default:            dispatch_sync([GCDHelper gcdMainQueue], block);            break;    }}+ (void) gcdPerformBlockOnGlobalQueue:(GCDBlock) block feature:(PerformBlockFeature) feature priority:(GlobalQueuePriority) priority{    switch (feature)    {        case PerformBlockFeatureChoke:            dispatch_sync([GCDHelper gcdGlobalQueue:priority], block);            break;                    case PerformBlockFeatureUnchoke:            dispatch_async([GCDHelper gcdGlobalQueue:priority], block);            break;                    default:            dispatch_sync([GCDHelper gcdGlobalQueue:GlobalQueuePriorityDefault], block);            break;    }}+ (void) gcdPerformBlockOnCustomQueue:(GCDBlock) block feature:(PerformBlockFeature) feature name:(NSString *) queueName{    switch (feature)    {        case PerformBlockFeatureChoke:            dispatch_sync([GCDHelper gcdCustomQueue:queueName], block);            break;                    case PerformBlockFeatureUnchoke:            dispatch_async([GCDHelper gcdCustomQueue:queueName], block);            break;                    default:            dispatch_sync([GCDHelper gcdCustomQueue:@"com.GCDHelper.Queue"], block);            break;    }}//后台执行+ (void) gcdPerformBlockAsynchronous:(GCDBlock) block{    [GCDHelper gcdPerformBlockOnGlobalQueue:block                                    feature:PerformBlockFeatureUnchoke                                   priority:GlobalQueuePriorityDefault];}//后台获取数据后,回到主线程+ (void) gcdPerformBlockAsynchronous:(GCDBlock) blockAsyn                   finishOnMainQueue:(GCDBlock) blockM{    dispatch_async([GCDHelper gcdGlobalQueue:GlobalQueuePriorityDefault], ^{        blockAsyn();        dispatch_async([GCDHelper gcdMainQueue], ^{            blockM();        });    });}#pragma mark -#pragma mark 队列延迟时间执行方法+ (void) gcdPerformBlock:(GCDBlock) block onQueue:(dispatch_queue_t) queue delaySecond:(int64_t) second{    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, second * NSEC_PER_SEC);    dispatch_after(popTime, queue, block);}#pragma mark -#pragma mark 只执行一次+ (void) gcdPerformBlockOnce:(GCDBlock) block{    static dispatch_once_t onceToken;    dispatch_once(&onceToken, block);}#pragma mark -#pragma mark 无序并发+ (void) gcdBatchPerformBlocks:(NSArray *) blockArray finally:(GCDBlock) finallyBlock{    [blockArray retain];        dispatch_queue_t queue = [GCDHelper gcdGlobalQueue:GlobalQueuePriorityDefault];    dispatch_group_t group = dispatch_group_create();        for(GCDBlock block in blockArray)    {        dispatch_group_async(group, queue, ^{            block();        });    }    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);        dispatch_async([GCDHelper gcdGlobalQueue:GlobalQueuePriorityDefault], ^{        finallyBlock();    });        dispatch_release(group);        [blockArray release];}+ (void) gcdBatchPerformBlockWithData:(NSArray *) dataArray          maxConcurrentOperationCount:(uint) count                          handleBlock:(GCDBlock1_Obj) block                              finally:(GCDBlock1_Obj) finallyBlock{    [dataArray retain];        dispatch_queue_t queue = [GCDHelper gcdGlobalQueue:GlobalQueuePriorityDefault];    dispatch_group_t group = dispatch_group_create();    dispatch_semaphore_t semaphore = dispatch_semaphore_create(count);    for(id obj in dataArray)    {        NSLog(@"并发中");        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);        dispatch_group_async(group, queue, ^{            block(obj);            dispatch_semaphore_signal(semaphore);        });    }        dispatch_group_wait(group, DISPATCH_TIME_FOREVER);    dispatch_group_notify(group, queue, ^{        finallyBlock(dataArray);    });    dispatch_release(group);        [dataArray release];}#pragma mark -#pragma mark 图片下载- (void) gcdImageWithURLString:(NSString *) URLString{    [self gcdImageWithURLString:URLString completion:nil];}- (void) gcdImageWithURLString:(NSString *) URLString completion:(GCDBlock2_Obj_Obj) completion{    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{                NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];        [request setURL:[NSURL URLWithString:URLString]];        [request setHTTPMethod:@"GET"];        NSData *returnData = [NSURLConnection sendSynchronousRequest:request                                                   returningResponse:nil                                                               error:nil];        [request release];                UIImage *image  = [UIImage imageWithData:returnData];                if (image)        {            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{                completion(image, URLString);            });        } else        {            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{                completion(image, URLString);            });        }    });}@end#pragma mark -#pragma mark 网络部分@implementation GCDHelper (NetworkConnect)- (BOOL)isReachableWithFlags:(SCNetworkReachabilityFlags)flags{    BOOL connectionUP = YES;        if(!(flags & kSCNetworkReachabilityFlagsReachable))        connectionUP = NO;        if( (flags & (kSCNetworkReachabilityFlagsConnectionRequired | kSCNetworkReachabilityFlagsTransientConnection)) == (kSCNetworkReachabilityFlagsConnectionRequired | kSCNetworkReachabilityFlagsTransientConnection) )        connectionUP = NO;        return connectionUP;}-(void)reachabilityChanged:(SCNetworkReachabilityFlags)flags{    dispatch_async(dispatch_get_main_queue(), ^{        _netWorkBlock([self isReachableWithFlags:flags]);    });}static void TMReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info){    @autoreleasepool    {        [(GCDHelper *)info reachabilityChanged:flags];    }}- (void) gcdNetWorkGuarder:(NSString *) hostname withBlock:(GCDBlock1_Bool) block{    _netWorkBlock = block;        SCNetworkReachabilityRef ref = SCNetworkReachabilityCreateWithName(NULL, [hostname UTF8String]);    SCNetworkReachabilityContext context = { 0, NULL, NULL, NULL, NULL };    dispatch_queue_t queue = dispatch_queue_create("com.myself.reachability", NULL);    context.info = (void *)self;    SCNetworkReachabilitySetCallback(ref, TMReachabilityCallback, &context);    SCNetworkReachabilitySetDispatchQueue(ref, queue);}@end@implementation GCDHelper(HttpRequest)- (void) startPOSTHTTPRequest:(NSString *) URLString                       params:(NSDictionary *) params                      timeout:(NSTimeInterval) time                      success:(GCDHttpRequestBlock) successBlock                         fail:(GCDHttpRequestBlock) failBlock{    [params retain];    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{                __block NSURLResponse  *response = nil;        __block NSError *error = nil;        __block NSData *receiveData = nil;                NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];                [request setURL:[NSURL URLWithString:[URLString lowercaseString]]];        [request setHTTPMethod:@"POST"];        [request setCachePolicy:NSURLRequestUseProtocolCachePolicy];        [request setTimeoutInterval:time];                if (!request)        {            NSDictionary *errorInfo = [NSDictionary dictionaryWithObjectsAndKeys:@"发送请求失败", @"errorKey", nil];            error = [NSError errorWithDomain:@"www.myself.com" code:100 userInfo:errorInfo];                        dispatch_async(dispatch_get_main_queue(), ^{                successBlock(response, error, receiveData);            });                        return;        }                if (params != nil)        {            [request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@", BOUNDRY]           forHTTPHeaderField:@"Content-Type"];                        int len=512;            NSMutableData *postData =[NSMutableData dataWithCapacity:len];            [postData appendData:[[NSString stringWithFormat:@"--%@/r/n", BOUNDRY]                                  dataUsingEncoding:NSUTF8StringEncoding]];            int i=0;            int cnt = [params count];                        for (NSString *key in [params allKeys])            {                // NSString *str = [NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"/r/n/r/n", key];                [postData appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"/r/n/r/n", key] dataUsingEncoding:NSUTF8StringEncoding]];                                [postData  appendData: [[NSString stringWithFormat:@"%@",[params objectForKey:key]]                                        dataUsingEncoding:NSUTF8StringEncoding]];                if(i != cnt - 1)                {                    [postData appendData:[[NSString stringWithFormat:@"/r/n--%@/r/n", BOUNDRY]                                          dataUsingEncoding:NSUTF8StringEncoding]];                }                i++ ;            }            [postData  appendData:[[NSString stringWithFormat:@"/r/n--%@--/r/n", BOUNDRY]                                   dataUsingEncoding:NSUTF8StringEncoding]];                        [request  setHTTPBody:postData];        }                receiveData = [[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error] retain];        if (!error)        {            dispatch_async(dispatch_get_main_queue(), ^{                successBlock(response, nil, receiveData);            });        }        else        {            dispatch_async(dispatch_get_main_queue(), ^{                successBlock(response, error, receiveData);            });        }                [request release];    });        [params release];}- (void) startGETHTTPRequest:(NSString *) URLString                      params:(NSDictionary *) params                     timeout:(NSTimeInterval) time                     success:(GCDHttpRequestBlock) successBlock                        fail:(GCDHttpRequestBlock) failBlock{    [params retain];        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{        __block NSURLResponse  *response = nil;        __block NSError *error = nil;        __block NSData *receiveData = nil;                NSMutableString *paramsString = [[NSMutableString alloc] init];        for(NSString *key in params)        {            [paramsString appendFormat:@"&%@=%@", key, [params objectForKey:key]];        }        NSString *requestString = [[NSString alloc] initWithFormat:@"%@%@", URLString, paramsString];        NSURL *reqUrl = [[NSURL alloc] initWithString:requestString];                [paramsString release];        [requestString release];                NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];                [request setURL:reqUrl];        [request setHTTPMethod:@"GET"];        [request setCachePolicy:NSURLRequestUseProtocolCachePolicy];        [request setTimeoutInterval:time];                [reqUrl release];            if (request)        {            receiveData = [[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error] retain];        }                if (!error)        {            dispatch_async(dispatch_get_main_queue(), ^{                successBlock(response, nil, receiveData);            });        }        else        {            dispatch_async(dispatch_get_main_queue(), ^{                successBlock(response, error, receiveData);            });        }                [request release];    });        [params release];}- (void) gcdHttpRequestWithURL:(NSString *) URLString                    httpMethod:(GCDHelperHttpRequestMethod) method                        params:(NSDictionary *) params                       timeout:(NSTimeInterval) time                       success:(GCDHttpRequestBlock) successBlock                          fail:(GCDHttpRequestBlock) failBlock{    switch (method)    {        case GCDHelperHttpRequestMethodGET:        {            [self startGETHTTPRequest:URLString params:params timeout:time success:successBlock fail:failBlock];            break;        }        case GCDHelperHttpRequestMethodPOST:        {            [self startPOSTHTTPRequest:URLString params:params timeout:time success:successBlock fail:failBlock];            break;        }        default:            break;    }}@end




用法举例:

一、基本概念举例:

#import <UIKit/UIKit.h>@interface BaseViewController : UIViewController{    IBOutlet UITextField *field1;    IBOutlet UITextField *field2;    IBOutlet UITextField *field3;        IBOutlet UITextField *textField;        dispatch_queue_t queue;}- (IBAction) calculate:(id)sender;- (IBAction) operationQueue:(id)sender;- (IBAction) gcd:(id)sender;- (IBAction) notchoke:(id)sender;- (IBAction) choke:(id)sender;- (IBAction) getUIData:(id)sender;- (IBAction)startQueue:(id)sender;- (IBAction)suspendQueue:(id)sender;- (IBAction)resumeQueue:(id)sender;@end

#import "BaseViewController.h"@implementation BaseViewController- (void) dealloc{    dispatch_release(queue);        [super dealloc];}- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil{    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];    if (self) {        queue = dispatch_queue_create("sss", NULL);    }    return self;}- (void)viewDidLoad{    [super viewDidLoad];    // Do any additional setup after loading the view from its nib.}- (void) longTask:(id) sender{    NSMutableArray *arr = [NSMutableArray array];    for (int i = 0; i < 1000; i++) {                [arr addObject:[NSMutableArray arrayWithObject:@(i)]];        NSLog(@"longTask:%d", i);    }}- (void) longTaskOther:(id) sender{    NSMutableArray *arr = [NSMutableArray array];    for (int i = 0; i < 10000; i++) {                [arr addObject:[NSMutableArray arrayWithObject:@(i)]];        NSLog(@"longTaskOther:%d", i);    }}- (IBAction) calculate:(id)sender{    field3.text = [NSString stringWithFormat:@"%f", [field1.text floatValue] - [field2.text floatValue]];}- (IBAction) operationQueue:(id)sender;{    NSOperationQueue *aqueue = [NSOperationQueue new];    NSInvocationOperation *operation = [[NSInvocationOperation alloc]                                        initWithTarget:self                                        selector:@selector(longTask:)                                        object:nil];    NSInvocationOperation *operation1 = [[NSInvocationOperation alloc]                                        initWithTarget:self                                        selector:@selector(longTaskOther:)                                        object:nil];        [aqueue addOperation:operation];    [aqueue addOperation:operation1];        [operation release];    [operation1 release];}- (IBAction) gcd:(id)sender  //3.192999{    [GCDHelper gcdPerformBlockAsynchronous:^{        NSMutableArray *arr = [NSMutableArray array];        for (int i = 0; i < 1000; i++) {                        [arr addObject:[NSMutableArray arrayWithObject:@(i)]];            NSLog(@"longTask:%d", i);        }    }];        [GCDHelper gcdPerformBlockAsynchronous:^{        NSMutableArray *arr = [NSMutableArray array];        for (int i = 0; i < 10000; i++) {                        [arr addObject:[NSMutableArray arrayWithObject:@(i)]];            NSLog(@"longTaskOther:%d", i);        }    }];}//////////////////////////////////////////////////////- (IBAction)notchoke:(id)sender{    dispatch_async(dispatch_get_main_queue(), ^{        NSLog(@"qqq");    });    NSLog(@"不阻塞");}//Calls to dispatch_sync() targeting the current queue will result//* in dead-lock. Use of dispatch_sync() is also subject to the same//* multi-party dead-lock problems that may result from the use of a mutex.//* Use of dispatch_async() is preferred.//在当前队列上调用dispatch_sync() 会导致死锁。调用dispatch_sync(),并使用mutex 经常会导致多方死锁问题。- (IBAction) choke:(id)sender{    dispatch_queue_t exampleQueue;        int i = 3;    switch (i) {        case 0:            exampleQueue = dispatch_get_global_queue(0, 0);            break;        case 1:            exampleQueue = dispatch_queue_create("com.abc.xxx", NULL);            break;        case 2:            exampleQueue = dispatch_get_current_queue();            break;        case 3:            exampleQueue = dispatch_get_main_queue();            break;                    default:            exampleQueue = dispatch_get_global_queue(0, 0);            break;    }        dispatch_sync( exampleQueue,^{        [self longTask:nil];    });        NSLog(@"task finish");}- (IBAction) getUIData:(id)sender{    dispatch_async(dispatch_get_global_queue(0, 0), ^{                __block NSString *stringValue;        dispatch_sync(dispatch_get_main_queue(), ^{            stringValue = [textField.text copy];        });                [stringValue retain];                NSLog(@"stringValue:%@", stringValue);    });}//一个要注意的地方是,dispatch queue的挂起是block粒度的。换句话说,挂起一个queue并不会将当前正在执行的block挂起。它会允许当前执行的block执行完毕,然后后续的block不再会被执行,直至queue被恢复。//还有一个注意点:从man页上得来的:如果你挂起了一个queue或者source,那么销毁它之前,必须先对其进行恢复。- (IBAction)startQueue:(id)sender{    dispatch_async(queue, ^{        for (int i = 0; i < 10000; i++) {            NSLog(@"taskA");        }    });        dispatch_async(queue, ^{        for (int i = 0; i < 10000; i++) {            NSLog(@"taskB");        }    });        dispatch_async(queue, ^{        for (int i = 0; i < 10000; i++) {            NSLog(@"taskC");        }    });}- (IBAction)suspendQueue:(id)sender{    NSLog(@"Queue suspend");    dispatch_suspend(queue);}- (IBAction)resumeQueue:(id)sender{    NSLog(@"Queue resume");    dispatch_resume(queue);}

二、基本用法举例

例子1:

#import <UIKit/UIKit.h>@interface OneViewController : UIViewController//无序并发- (IBAction)selector0:(id)sender;//无序并发处理数据- (IBAction)selector100:(id)sender;//执行一次- (IBAction)selector1:(id)sender;//异步/后台执行- (IBAction)selector2:(id)sender;//后台执行,然后返回主线程- (IBAction)selector3:(id)sender;//三种队列执行- (IBAction)selector4:(UISegmentedControl *)sender;//延迟执行- (IBAction)selector5:(id)sender;@end

#import "OneViewController.h"@interface OneViewController ()@end@implementation OneViewController- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil{    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];    if (self) {        // Custom initialization    }    return self;}- (void)viewDidLoad{    [super viewDidLoad];}- (NSMutableArray *) getBlockArray{    NSMutableArray *arr = [[NSMutableArray array] retain];        GCDBlock b0 = ^{ NSLog(@"无序并发: 0"); sleep(3); }; [arr addObject:b0];    GCDBlock b1 = ^{ NSLog(@"无序并发: 1"); }; [arr addObject:b1];    GCDBlock b2 = ^{ NSLog(@"无序并发: 2"); }; [arr addObject:b2];    GCDBlock b3 = ^{ NSLog(@"无序并发: 3"); }; [arr addObject:b3];    GCDBlock b4 = ^{ NSLog(@"无序并发: 4"); }; [arr addObject:b4];    GCDBlock b5 = ^{ NSLog(@"无序并发: 5"); }; [arr addObject:b5];    GCDBlock b6 = ^{ NSLog(@"无序并发: 6"); }; [arr addObject:b6];    GCDBlock b7 = ^{ NSLog(@"无序并发: 7"); }; [arr addObject:b7];    GCDBlock b8 = ^{ NSLog(@"无序并发: 8"); }; [arr addObject:b8];    GCDBlock b9 = ^{ NSLog(@"无序并发: 9"); }; [arr addObject:b9];    GCDBlock b10 = ^{ NSLog(@"无序并发: 10"); }; [arr addObject:b10];    GCDBlock b11 = ^{ NSLog(@"无序并发: 11"); }; [arr addObject:b11];    GCDBlock b12 = ^{ NSLog(@"无序并发: 12"); }; [arr addObject:b12];    GCDBlock b13 = ^{ NSLog(@"无序并发: 13"); }; [arr addObject:b13];    GCDBlock b14 = ^{ NSLog(@"无序并发: 14"); }; [arr addObject:b14];    GCDBlock b15 = ^{ NSLog(@"无序并发: 15"); }; [arr addObject:b15];        return arr;}//无序并发- (IBAction)selector0:(id)sender{    [GCDHelper gcdBatchPerformBlocks:[self getBlockArray] finally:^{        NSLog(@"一组有序并发完成");    }];    //    NSLog(@"一组无序并发完成");}- (IBAction)selector100:(id)sender{    NSMutableArray *arr = [NSMutableArray array];    for (int i = 0; i < 100; i++) {        [arr addObject:[NSMutableArray array]];    }        __block int i = 0;    [GCDHelper gcdBatchPerformBlockWithData:arr maxConcurrentOperationCount:10 handleBlock:^(id object) {                sleep(1);        NSMutableArray *arr = (NSMutableArray *)object;        [arr addObject:@(i)];        i++;    } finally:^(id object) {        NSLog(@"arr:%@", object);    }];}- (IBAction)selector1:(id)sender{    [GCDHelper gcdPerformBlockOnce:^{        NSLog(@"别想让我执行第二次");    }];    NSLog(@"不执行~");}//异步/后台执行- (IBAction)selector2:(id)sender{    [GCDHelper gcdPerformBlockAsynchronous:^{        sleep(3);         NSLog(@"全局队列执行完成");    }];    NSLog(@"全局队列执行,不影响主队列");}//后台执行,然后返回主线程- (IBAction)selector3:(id)sender{    [GCDHelper gcdPerformBlockAsynchronous:^{               for (int i = 0; i< 10; i++)        {            NSLog(@"全局队列执行: %d", i);        }            } finishOnMainQueue:^{        NSLog(@"回到主队列");    }];}//三种队列执行- (IBAction)selector4:(UISegmentedControl *)sender{    switch (sender.selectedSegmentIndex) {        case 0:        {            [GCDHelper gcdPerformBlockOnMainQueue:^{                NSLog(@"主队列执行");            } feature:PerformBlockFeatureUnchoke];            break;        }        case 1:        {            [GCDHelper gcdPerformBlockOnGlobalQueue:^{                NSLog(@"全局队列执行");            } feature:PerformBlockFeatureUnchoke priority:GlobalQueuePriorityDefault];            break;        }        case 2:        {            [GCDHelper gcdPerformBlockOnCustomQueue:^{                NSLog(@"自创建队列执行");            } feature:PerformBlockFeatureUnchoke name:@"com.abc.bcd"];            break;        }                    default:            break;    }}//延迟执行- (IBAction)selector5:(id)sender{    NSLog(@"延迟 2s 执行");    [GCDHelper gcdPerformBlock:^{        NSLog(@"执行完毕");    } onQueue:[GCDHelper gcdMainQueue] delaySecond:2];}@end

例子2:

#import <UIKit/UIKit.h>@interface MulthreadConcurrentVC : UIViewController@end

#import "MulthreadConcurrentVC.h"/*  如何在GCD中快速的控制并发呢?答案就是 dispatch_semaphore,对经常做unix开发的人来讲,我所介绍的内容可能就显得非常入门级了,信号量在他们的多线程开发中再平常不过了。 在GCD中有三个函数是semaphore的操作,分别是: dispatch_semaphore_create          创建一个semaphore dispatch_semaphore_signal          发送一个信号 dispatch_semaphore_wait              等待信号 简单的介绍一下这三个函数,第一个函数有一个整形的参数,我们可以理解为信号的总量,dispatch_semaphore_signal是发送一个信号,自然会让信号总量加1,dispatch_semaphore_wait等待信号,当信号总量少于0的时候就会一直等待,否则就可以正常的执行,并让信号总量减少1,根据这样的原理,我们便可以快速的创建一个并发控制。  *//* 简单的介绍一下这一段代码,创建了一个初使值为10的semaphore,每一次for循环都会创建一个新的线程,线程结束的时候会发送一个信号,线程创建之前会信号等待,所以当同时创建了10个线程之后,for循环就会阻塞,等待有线程结束之后会增加一个信号才继续执行,如此就形成了对并发的控制,如上就是一个并发数为10的一个线程队列。 */@implementation MulthreadConcurrentVC- (void) loadView{    [super loadView];}- (void)aSelector:(id)sender{    dispatch_group_t group = dispatch_group_create();    dispatch_semaphore_t semaphore = dispatch_semaphore_create(10);    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);    for (int i = 0; i < 100; i++)    {        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);        dispatch_group_async(group, queue, ^{            NSLog(@"%i",i);            sleep(2);            dispatch_semaphore_signal(semaphore);        });    }    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);    dispatch_release(group);    dispatch_release(semaphore);}- (void)viewDidLoad{    [super viewDidLoad];        UIButton *bt = [UIButton buttonWithType:UIButtonTypeRoundedRect];    bt.frame = CGRectMake(100, 100, 120, 120);    [bt addTarget:self action:@selector(aSelector:) forControlEvents:UIControlEventTouchUpInside];    [self.view addSubview:bt];}

三、GCD实际应用举例

#import <UIKit/UIKit.h>#import "GCDHelper.h"@interface TableViewController : UITableViewController@end

#import "TableViewController.h"#import "CustomCell.h"#import <objc/runtime.h>static char * const kIndexPathAssociationKey = "JK_indexPath";@interface TableViewController ()@end@implementation TableViewController- (id)initWithStyle:(UITableViewStyle)style{    self = [super initWithStyle:style];    if (self) {        // Custom initialization    }    return self;}- (void)viewDidLoad{    [super viewDidLoad];    self.clearsSelectionOnViewWillAppear = NO;    self.navigationItem.rightBarButtonItem = self.editButtonItem;}- (void)didReceiveMemoryWarning{    [super didReceiveMemoryWarning];    // Dispose of any resources that can be recreated.}#pragma mark - Table view data source- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{    return 1;}- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{    return 100;}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{    static NSString *CellIdentifier = @"Cell";    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];        if (cell == nil) {        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];        UIImageView *im = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 40)];        im.tag = 10;        [cell addSubview:im];        [im release];    }        return cell;}- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{//    http://localhost:8888/Imgs/img0.png//    http://theme.blogcn.com/wp-content/themes/coffee-desk/images/rsscoffee.PNG        NSString *imgURLStr = nil;    if ((indexPath.row % 2) == 0)    {        imgURLStr = @"http://localhost:8888/Imgs/img0.png";    } else    {        imgURLStr = @"http://localhost:8888/Imgs/img1.png";    }        GCDHelper *hp = [GCDHelper new];    [hp gcdImageWithURLString:imgURLStr                   completion:^(id object1, id object2) {                                           dispatch_async(dispatch_get_main_queue(), ^{                           UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];                           [(UIImageView *)[cell viewWithTag:10] setImage:(UIImage *)object1];                       });                   }];}#pragma mark - Table view delegate- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{}#pragma mark -#pragma mark - cell重用- (void)tableViewCellIsPreparingForReuse:(NSNotification *)notification{if ([[notification object] isKindOfClass:[CustomCell class]]) {CustomCell *cell = (CustomCell *)[notification object];objc_setAssociatedObject(cell, kIndexPathAssociationKey, nil, OBJC_ASSOCIATION_RETAIN);[[cell imageView] setImage:nil];}}@end

#import <UIKit/UIKit.h>extern NSString * const kJKPrepareForReuseNotification;@interface CustomCell : UITableViewCell@end

#import "CustomCell.h"NSString * const kJKPrepareForReuseNotification = @"JKCallbacksTableViewCell_PrepareForReuse";@implementation CustomCell- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];    if (self) {        //如果cell 的图片发生改变,当cell重用的时候,刷新图片        [[self imageView] addObserver:self   forKeyPath:@"image"  options:NSKeyValueObservingOptionOld  context:NULL];    }    return self;}- (void)observeValueForKeyPath:(NSString *)keyPath  ofObject:(id)objectchange:(NSDictionary *)change   context:(void *)context{    NSLog(@"observeValueForKeyPath");    if (object == [self imageView] &&[keyPath isEqualToString:@"image"] &&([change objectForKey:NSKeyValueChangeOldKey] == nil || [change objectForKey:NSKeyValueChangeOldKey] == [NSNull null]))    {[self setNeedsLayout];}}- (void)prepareForReuse{[[NSNotificationCenter defaultCenter] postNotificationName:kJKPrepareForReuseNotificationobject:self];[super prepareForReuse];}@end

----------------------------------------------

#import <Foundation/Foundation.h>@interface NetGuarder : NSObject+ (NetGuarder *) shareNetGuarder;@end

#import "NetGuarder.h"@implementation NetGuarderstatic NetGuarder *guarder = nil;+ (void) getNetConnectMsg{    GCDHelper *hp = [GCDHelper new];    [hp gcdNetWorkGuarder:@"www.baidu.com" withBlock:^(BOOL flag) {        if (flag)        {            NSLog(@"Net connect");        } else        {            NSLog(@"Net not connect");        }    }];}+ (NetGuarder *) shareNetGuarder{    static dispatch_once_t predicate;    dispatch_once(&predicate, ^{                NSLog(@"单例创建");        guarder = [[self alloc] init];                [NetGuarder getNetConnectMsg];    });        return guarder;}@end

-------------------------------------------

#import <UIKit/UIKit.h>@interface URLConViewController : UIViewController <NSURLConnectionDataDelegate>{    IBOutlet UISegmentedControl *segment;    IBOutlet UILabel *label;}@end

#import "URLConViewController.h"typedef struct _INT{    int t1;    }INT_STRUCT;@interface URLConViewController (){    NSMutableData *receivedData;    BOOL finished;}@end@implementation URLConViewController- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil{    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];    if (self)    {        receivedData = [[NSMutableData data] retain];    }    return self;}- (void)viewDidLoad{    [super viewDidLoad];}- (void)didReceiveMemoryWarning{    [super didReceiveMemoryWarning];}- (void) cleanText{    label.text = @"";}- (IBAction)segmentAction:(UISegmentedControl *)sender{    switch (sender.selectedSegmentIndex) {        case 0:        {            [self sendRequestSync];            break;        }        case 1:        {            [self sendRequestAsync];            break;        }        case 2:        {            [self sendRequestAsyncOther];            break;        }        case 3:        {            [self gcdRequest];            break;        }                    default:            break;    }}#pragma mark -#pragma mark  GCDRequest- (void) gcdRequest{    GCDHelper *hp = [GCDHelper new];        [hp gcdHttpRequestWithURL:@"http://localhost:8888/test.php"                   httpMethod:GCDHelperHttpRequestMethodGET                       params:[NSDictionary dictionary]                      timeout:5.0f                      success:^(NSURLResponse *response, NSError *error, NSData *data) {                          if (data && (!error))                          {                              label.text = [[data objectFromJSONData] description];                          }                                                }                         fail:^(NSURLResponse *response, NSError *error, NSData *data) {                             if (error)                             {                                 label.text = [error description];                             }                         }];}#pragma mark -#pragma mark  sendRequestSync- (void) sendRequestSync{    [self cleanText];        NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];        [request setURL:[NSURL URLWithString:@"http://localhost:8888/test.php"]];    [request setHTTPMethod:@"GET"];        NSError *error = nil;    NSData *data = [NSURLConnection sendSynchronousRequest:request                                         returningResponse:nil                                                     error:&error];        if (data && (!error))    {        label.text = [[data objectFromJSONData] description];    }}#pragma mark -#pragma mark  sendRequestAsync- (void) sendRequestAsync{    finished = NO;        NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];    [request setURL:[NSURL URLWithString:@"http://localhost:8888/test1.php"]];    [request setHTTPMethod:@"GET"];    [request setCachePolicy:NSURLRequestUseProtocolCachePolicy];    [request setTimeoutInterval:5.0f];        NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request                                                                  delegate:self                                                          startImmediately:YES];        [connection start];    //    但是异步模式下带来了一个新的问题,很多情况下,网络请求不在主线程,或者界面等待网络结果,不在主线程的时候,调用线程如果生命周期over,下面这些可能都没有调用到,导致得不到想要得效果,所以需要在NSURLConnection请求后面加点东西来阻塞    while(!finished) {                [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];            }}// 收到回应- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{    // 注意这里将NSURLResponse对象转换成NSHTTPURLResponse对象才能去    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;        if ([response respondsToSelector:@selector(allHeaderFields)])    {        NSDictionary *dictionary = [httpResponse allHeaderFields];        NSLog(@"allHeaderFields: %@",dictionary);    }    [receivedData setLength:0];}// 接收数据- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{    NSLog(@"get some data");    [receivedData appendData:data];}// 数据接收完毕- (void)connectionDidFinishLoading:(NSURLConnection *)connection{    NSString *results = [[NSString alloc] initWithBytes:[receivedData bytes]                                                 length:[receivedData length]                                               encoding:NSUTF8StringEncoding];        label.text = [[results objectFromJSONString] description];        finished = YES;}// 返回错误-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{    NSLog(@"Connection failed: %@", error);}#pragma mark -#pragma mark  sendRequestAsyncOther- (IBAction) sendRequestAsyncOther{    [self cleanText];        NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];    [request setURL:[NSURL URLWithString:@"http://localhost:8888/test2.php"]];    [request setHTTPMethod:@"GET"];    [request setCachePolicy:NSURLRequestUseProtocolCachePolicy];    [request setTimeoutInterval:5.0f];        [NSURLConnection sendAsynchronousRequest:request                                       queue:[NSOperationQueue new]                           completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {                                                              dispatch_async(dispatch_get_main_queue(), ^{                                   label.text = [[data objectFromJSONData] description];                               });                                                          }];}@end

----------------------------------------------

#import <Foundation/Foundation.h>/** Simple GCD-based timer based on NSTimer. Starts immediately and stops when deallocated. This avoids many of the typical problems with NSTimer: * RNTimer runs in all modes (unlike NSTimer) * RNTimer runs when there is no runloop (unlike NSTimer) * Repeating RNTimers can easily avoid retain loops (unlike NSTimer)*/@interface RNTimer : NSObject/**--------------------------------------------------------------------------------------- @name Creating a Timer -----------------------------------------------------------------------------------------*//** Creates and returns a new repeating RNTimer object and starts running it After `seconds` seconds have elapsed, the timer fires, executing the block. You will generally need to use a weakSelf pointer to avoid a retain loop. The timer is attached to the main GCD queue. @param seconds The number of seconds between firings of the timer. Must be greater than 0. @param block Block to execute. Must be non-nil @return A new RNTimer object, configured according to the specified parameters.*/+ (RNTimer *)repeatingTimerWithTimeInterval:(NSTimeInterval)seconds block:(dispatch_block_t)block;/**--------------------------------------------------------------------------------------- @name Firing a Timer -----------------------------------------------------------------------------------------*//** Causes the block to be executed. This does not modify the timer. It will still fire on schedule.*/- (void)fire;/**--------------------------------------------------------------------------------------- @name Stopping a Timer -----------------------------------------------------------------------------------------*//** Stops the receiver from ever firing again Once invalidated, a timer cannot be reused.*/- (void)invalidate;@end

#import "RNTimer.h"@interface RNTimer ()@property (nonatomic, readwrite, copy) dispatch_block_t block;@property (nonatomic, readwrite, assign) dispatch_source_t source;@end@implementation RNTimer@synthesize block = _block;@synthesize source = _source;+ (RNTimer *)repeatingTimerWithTimeInterval:(NSTimeInterval)seconds                                      block:(void (^)(void))block {  NSParameterAssert(seconds);  NSParameterAssert(block);  RNTimer *timer = [[self alloc] init];  timer.block = block;  timer.source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER,                                        0, 0,                                        dispatch_get_main_queue());      uint64_t nsec = (uint64_t)(seconds * NSEC_PER_SEC);  dispatch_source_set_timer(timer.source,                            dispatch_time(DISPATCH_TIME_NOW, nsec),                            nsec, 0);  dispatch_source_set_event_handler(timer.source, block);  dispatch_resume(timer.source);  return timer;}- (void)invalidate {  if (self.source) {    dispatch_source_cancel(self.source);    dispatch_release(self.source);    self.source = nil;  }  self.block = nil;}- (void)dealloc {  [self invalidate];}- (void)fire {  self.block();}@end




完整的项目链接:http://pan.baidu.com/share/link?shareid=386371&uk=3674861929

转载请保留,原文链接:http://write.blog.csdn.net/postedit/8708667

若发现有不合适或错误之处,还请批评指正,不胜感激。