ios GCD的使用及封装

时间:2023-03-09 01:32:15
ios GCD的使用及封装

ios GCD的使用及封装

ios GCD的使用及封装

ios GCD的使用及封装

ios GCD的使用及封装

ios GCD的使用及封装

ios GCD的使用及封装

ios GCD的使用及封装

ios GCD的使用及封装

ios GCD的使用及封装

ios GCD的使用及封装

ios GCD的使用及封装

ios GCD的使用及封装

ios GCD的使用及封装

ios GCD的使用及封装

ios GCD的使用及封装

ios GCD的使用及封装

ios GCD的使用及封装

实现代码:

CGDHelper

 /*
* Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法。
* 系统要求:iOS4.0以上。
*/ #import <Foundation/Foundation.h> /////////////////////////////////////// enum 声明 ///////////////////////////////////////////////// //队列优先级
typedef enum
{
GlobalQueuePriorityDefault = ,
GlobalQueuePriorityHigh = ,
GlobalQueuePriorityLow = -,
GlobalQueuePriorityBackground = INT16_MIN } GlobalQueuePriority; //阻塞、非阻塞
typedef enum
{
PerformBlockFeatureChoke,
PerformBlockFeatureUnchoke } PerformBlockFeature; //网络请求方法
typedef enum GCDHelperHttpRequestMethod
{
GCDHelperHttpRequestMethodGET = ,
GCDHelperHttpRequestMethodPOST } GCDHelperHttpRequestMethod; /////////////////////////////////////// Block 声明 ///////////////////////////////////////////////// //返回值void
typedef 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 15 static 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, );
break;
case GlobalQueuePriorityHigh:
return dispatch_get_global_queue(priority, );
break;
case GlobalQueuePriorityLow:
return dispatch_get_global_queue(priority, );
break;
case GlobalQueuePriorityBackground:
return dispatch_get_global_queue(priority, );
break; default:
return dispatch_get_global_queue(GlobalQueuePriorityDefault, );
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, ), ^{ 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, ), ^{
completion(image, URLString);
});
} else
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, ), ^{
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 = { , 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, ), ^{ __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: 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=;
NSMutableData *postData =[NSMutableData dataWithCapacity:len];
[postData appendData:[[NSString stringWithFormat:@"--%@/r/n", BOUNDRY]
dataUsingEncoding:NSUTF8StringEncoding]];
int i=;
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 - )
{
[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, ), ^{
__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

用法举例:

一、基本概念举例:

 [cpp] view plaincopyprint?

     #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 [cpp] view plaincopyprint? #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 = ; i < ; i++) { [arr addObject:[NSMutableArray arrayWithObject:@(i)]];
NSLog(@"longTask:%d", i);
}
} - (void) longTaskOther:(id) sender
{
NSMutableArray *arr = [NSMutableArray array];
for (int i = ; i < ; 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 = ; i < ; i++) { [arr addObject:[NSMutableArray arrayWithObject:@(i)]];
NSLog(@"longTask:%d", i);
}
}]; [GCDHelper gcdPerformBlockAsynchronous:^{
NSMutableArray *arr = [NSMutableArray array];
for (int i = ; i < ; 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 = ;
switch (i) {
case :
exampleQueue = dispatch_get_global_queue(, );
break;
case :
exampleQueue = dispatch_queue_create("com.abc.xxx", NULL);
break;
case :
exampleQueue = dispatch_get_current_queue();
break;
case :
exampleQueue = dispatch_get_main_queue();
break; default:
exampleQueue = dispatch_get_global_queue(, );
break;
} dispatch_sync( exampleQueue,^{
[self longTask:nil];
}); NSLog(@"task finish");
} - (IBAction) getUIData:(id)sender
{
dispatch_async(dispatch_get_global_queue(, ), ^{ __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 = ; i < ; i++) {
NSLog(@"taskA");
}
}); dispatch_async(queue, ^{
for (int i = ; i < ; i++) {
NSLog(@"taskB");
}
}); dispatch_async(queue, ^{
for (int i = ; i < ; 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 [cpp] view plaincopyprint? #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(); }; [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 = ; i < ; i++) {
[arr addObject:[NSMutableArray array]];
} __block int i = ;
[GCDHelper gcdBatchPerformBlockWithData:arr maxConcurrentOperationCount: handleBlock:^(id object) { sleep();
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();
NSLog(@"全局队列执行完成");
}];
NSLog(@"全局队列执行,不影响主队列");
} //后台执行,然后返回主线程
- (IBAction)selector3:(id)sender
{
[GCDHelper gcdPerformBlockAsynchronous:^{ for (int i = ; i< ; i++)
{
NSLog(@"全局队列执行: %d", i);
} } finishOnMainQueue:^{
NSLog(@"回到主队列");
}];
} //三种队列执行
- (IBAction)selector4:(UISegmentedControl *)sender
{
switch (sender.selectedSegmentIndex) {
case :
{
[GCDHelper gcdPerformBlockOnMainQueue:^{
NSLog(@"主队列执行");
} feature:PerformBlockFeatureUnchoke];
break;
}
case :
{
[GCDHelper gcdPerformBlockOnGlobalQueue:^{
NSLog(@"全局队列执行");
} feature:PerformBlockFeatureUnchoke priority:GlobalQueuePriorityDefault];
break;
}
case :
{
[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:];
} @end
     #import <UIKit/UIKit.h>  

     @interface MulthreadConcurrentVC : UIViewController  

     @end  

 [cpp] view plaincopyprint?

     #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();
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, );
for (int i = ; i < ; i++)
{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_group_async(group, queue, ^{
NSLog(@"%i",i);
sleep();
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(, , , );
[bt addTarget:self action:@selector(aSelector:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:bt];
}

三、GCD实际应用举例

     #import <UIKit/UIKit.h>  

     #import "GCDHelper.h"  

     @interface TableViewController : UITableViewController  

     @end  

 [cpp] view plaincopyprint?

     #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 ;
} - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return ;
} - (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(, , , )];
im.tag = ;
[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 % ) == )
{
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:] 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  

 [cpp] view plaincopyprint?

     #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)object
change:(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:kJKPrepareForReuseNotification
object:self]; [super prepareForReuse];
}
     #import <Foundation/Foundation.h>  

     @interface NetGuarder : NSObject  

     + (NetGuarder *) shareNetGuarder;  

     @end  
     #import "NetGuarder.h"  

     @implementation NetGuarder  

     static 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 :
{
[self sendRequestSync];
break;
}
case :
{
[self sendRequestAsync];
break;
}
case :
{
[self sendRequestAsyncOther];
break;
}
case :
{
[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:];
} // 接收数据
- (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,
, ,
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, );
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.****.net/postedit/8708667

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