实现代码:
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 声明 ///////////////////////////////////////////////// //返回值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, 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
#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]; }
#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)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]; } @end
#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 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
若发现有不合适或错误之处,还请批评指正,不胜感激。