ios GCD的使用及封装
实现代码:
CGDHelper
1 /* 2 * Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法。 3 * 系统要求:iOS4.0以上。 4 */ 5 6 #import <Foundation/Foundation.h> 7 8 /////////////////////////////////////// enum 声明 ///////////////////////////////////////////////// 9 10 //队列优先级 11 typedef enum 12 { 13 GlobalQueuePriorityDefault = 0, 14 GlobalQueuePriorityHigh = 2, 15 GlobalQueuePriorityLow = -2, 16 GlobalQueuePriorityBackground = INT16_MIN 17 18 } GlobalQueuePriority; 19 20 //阻塞、非阻塞 21 typedef enum 22 { 23 PerformBlockFeatureChoke, 24 PerformBlockFeatureUnchoke 25 26 } PerformBlockFeature; 27 28 //网络请求方法 29 typedef enum GCDHelperHttpRequestMethod 30 { 31 GCDHelperHttpRequestMethodGET = 0, 32 GCDHelperHttpRequestMethodPOST 33 34 } GCDHelperHttpRequestMethod; 35 36 /////////////////////////////////////// Block 声明 ///////////////////////////////////////////////// 37 38 //返回值void 39 typedef void (^GCDBlock) (void); 40 typedef void (^GCDBlock1_Size_t) (size_t index); 41 typedef void (^GCDBlock1_Int) (int index); 42 typedef void (^GCDBlock1_Bool) (BOOL flag); 43 typedef void (^GCDBlock1_Float) (float index); 44 typedef void (^GCDBlock1_Obj) (id object); 45 46 //返回值void,两个形式参数 47 typedef void (^GCDBlock2) (id object1, size_t index); 48 typedef void (^GCDBlock2_Obj_Int) (id object1, int index); 49 typedef void (^GCDBlock2_Obj_Obj) (id object1, id object2); 50 51 //有返回值 52 typedef id (^GCD_Obj_Block_Obj) (id object); 53 typedef id (^GCD_Obj_Block_Void) (void); 54 55 typedef void (^GCDHttpRequestBlock) (NSURLResponse *response, NSError *error, NSData *data); 56 57 58 /////////////////////////////////////// GCDHelper 声明 ///////////////////////////////////////////////// 59 60 @interface GCDHelper : NSObject 61 62 /* 获取3种队列 */ 63 + (dispatch_queue_t) gcdMainQueue; 64 + (dispatch_queue_t) gcdGlobalQueue:(GlobalQueuePriority) priority; 65 + (dispatch_queue_t) gcdCustomQueue:(NSString *) queueName; 66 67 //后台执行 68 + (void) gcdPerformBlockAsynchronous:(GCDBlock) block; 69 70 //后台获取数据后,回到主线程 71 + (void) gcdPerformBlockAsynchronous:(GCDBlock) blockAsyn 72 finishOnMainQueue:(GCDBlock) blockM; 73 74 75 /* 3种队列上执行Block 76 * 77 * 是否阻塞执行:(PerformBlockFeature) feature 78 * 全局队列优先级:(GlobalQueuePriority) priority 79 */ 80 + (void) gcdPerformBlockOnMainQueue:(GCDBlock) block feature:(PerformBlockFeature) feature; 81 82 + (void) gcdPerformBlockOnGlobalQueue:(GCDBlock) block 83 feature:(PerformBlockFeature) feature 84 priority:(GlobalQueuePriority) priority; 85 86 + (void) gcdPerformBlockOnCustomQueue:(GCDBlock) block 87 feature:(PerformBlockFeature) feature 88 name:(NSString *) queueName; 89 90 91 //延迟执行方法 92 + (void) gcdPerformBlock:(GCDBlock) block 93 onQueue:(dispatch_queue_t) queue 94 delaySecond:(int64_t) second; 95 96 97 //只执行一次 98 + (void) gcdPerformBlockOnce:(GCDBlock) block; 99 100 //并发 101 + (void) gcdBatchPerformBlocks:(NSArray *) blockArray finally:(GCDBlock) finallyBlock; 102 103 + (void) gcdBatchPerformBlockWithData:(NSArray *) dataArray 104 maxConcurrentOperationCount:(uint) count 105 handleBlock:(GCDBlock1_Obj) block 106 finally:(GCDBlock1_Obj) finallyBlock; 107 108 109 110 @end 111 112 /////////////////////////////////////// 图片下载 ///////////////////////////////////////////////// 113 114 @interface GCDHelper (ImageDownload) 115 116 - (void) gcdImageWithURLString:(NSString *) URLString; 117 - (void) gcdImageWithURLString:(NSString *) URLString completion:(GCDBlock2_Obj_Obj) completion; 118 119 @end 120 121 /////////////////////////////////////// 网络请求 ///////////////////////////////////////////////// 122 123 GCDBlock1_Bool _netWorkBlock; 124 @interface GCDHelper (NetworkConnect) 125 126 //网络连接判断、实时监控 127 - (void) gcdNetWorkGuarder:(NSString *) hostname withBlock:(GCDBlock1_Bool) block; 128 129 @end 130 131 132 @interface GCDHelper (HttpRequest) 133 134 //GCD请求网络(GET方式测试通过,POST方式测试未通过) 135 - (void) gcdHttpRequestWithURL:(NSString *) URLString 136 httpMethod:(GCDHelperHttpRequestMethod) method 137 params:(NSDictionary *) params 138 timeout:(NSTimeInterval) time 139 success:(GCDHttpRequestBlock) successBlock 140 fail:(GCDHttpRequestBlock) failBlock; 141 142 @end
1 #import "GCDHelper.h" 2 3 #import <SystemConfiguration/SystemConfiguration.h> 4 5 #import <sys/socket.h> 6 #import <netinet/in.h> 7 #import <netinet6/in6.h> 8 #import <arpa/inet.h> 9 #import <ifaddrs.h> 10 #import <netdb.h> 11 12 //Error 13 #define GCDHelperErrorURLISNULL [NSError errorWithDomain:@"please setup GCDHelper‘s url or urlString" code:100 userInfo:nil] 14 #define GCDHelperErrorRequestISNULL [NSError errorWithDomain:@"request can not be nil!" code:101 userInfo:nil] 15 #define GCDHelperErrorFileExist [NSError errorWithDomain:@"File Exist!" code:102 userInfo:nil] 16 #define GCDHelperErrorCreateFail [NSError errorWithDomain:@"Create File Fail!" code:103 userInfo:nil] 17 18 //下载的临时文件的后缀 19 #define kTHDownLoadTask_TempSuffix @".TempDownload" 20 //计算下载速度的取样时间 21 #define kTHDownLoadTimerInterval 2.0 22 //THDispatchQueue默认的并发数 23 #define kTHDispatchQueueDefaultConcurrentCount 10 24 25 #define kDefaultTimeoutInterval 15 26 27 28 static NSString * const BOUNDRY = @"--------------------------7d71a819230404"; 29 30 31 @implementation GCDHelper 32 33 - (void) dealloc 34 { 35 [super dealloc]; 36 } 37 38 - (id) init 39 { 40 if (self = [super init]) 41 { 42 } 43 44 return self; 45 } 46 47 #pragma mark - 48 #pragma mark 获取队列 49 50 + (dispatch_queue_t) gcdMainQueue 51 { 52 return dispatch_get_main_queue(); 53 } 54 55 + (dispatch_queue_t) gcdGlobalQueue:(GlobalQueuePriority) priority 56 { 57 switch (priority) 58 { 59 case GlobalQueuePriorityDefault: 60 return dispatch_get_global_queue(priority, 0); 61 break; 62 case GlobalQueuePriorityHigh: 63 return dispatch_get_global_queue(priority, 0); 64 break; 65 case GlobalQueuePriorityLow: 66 return dispatch_get_global_queue(priority, 0); 67 break; 68 case GlobalQueuePriorityBackground: 69 return dispatch_get_global_queue(priority, 0); 70 break; 71 72 default: 73 return dispatch_get_global_queue(GlobalQueuePriorityDefault, 0); 74 break; 75 } 76 } 77 78 + (dispatch_queue_t) gcdCustomQueue:(NSString *) queueName; 79 { 80 return dispatch_queue_create([queueName UTF8String], NULL); 81 } 82 83 #pragma mark - 84 #pragma mark 3种队列上执行Block 85 86 + (void) gcdPerformBlockOnMainQueue:(GCDBlock) block feature:(PerformBlockFeature) feature 87 { 88 switch (feature) 89 { 90 case PerformBlockFeatureChoke: 91 dispatch_sync([GCDHelper gcdMainQueue], block); 92 break; 93 94 case PerformBlockFeatureUnchoke: 95 dispatch_async([GCDHelper gcdMainQueue], block); 96 break; 97 98 default: 99 dispatch_sync([GCDHelper gcdMainQueue], block); 100 break; 101 } 102 } 103 104 + (void) gcdPerformBlockOnGlobalQueue:(GCDBlock) block feature:(PerformBlockFeature) feature priority:(GlobalQueuePriority) priority 105 { 106 switch (feature) 107 { 108 case PerformBlockFeatureChoke: 109 dispatch_sync([GCDHelper gcdGlobalQueue:priority], block); 110 break; 111 112 case PerformBlockFeatureUnchoke: 113 dispatch_async([GCDHelper gcdGlobalQueue:priority], block); 114 break; 115 116 default: 117 dispatch_sync([GCDHelper gcdGlobalQueue:GlobalQueuePriorityDefault], block); 118 break; 119 } 120 } 121 122 + (void) gcdPerformBlockOnCustomQueue:(GCDBlock) block feature:(PerformBlockFeature) feature name:(NSString *) queueName 123 { 124 switch (feature) 125 { 126 case PerformBlockFeatureChoke: 127 dispatch_sync([GCDHelper gcdCustomQueue:queueName], block); 128 break; 129 130 case PerformBlockFeatureUnchoke: 131 dispatch_async([GCDHelper gcdCustomQueue:queueName], block); 132 break; 133 134 default: 135 dispatch_sync([GCDHelper gcdCustomQueue:@"com.GCDHelper.Queue"], block); 136 break; 137 } 138 } 139 140 //后台执行 141 + (void) gcdPerformBlockAsynchronous:(GCDBlock) block 142 { 143 [GCDHelper gcdPerformBlockOnGlobalQueue:block 144 feature:PerformBlockFeatureUnchoke 145 priority:GlobalQueuePriorityDefault]; 146 } 147 148 //后台获取数据后,回到主线程 149 + (void) gcdPerformBlockAsynchronous:(GCDBlock) blockAsyn 150 finishOnMainQueue:(GCDBlock) blockM 151 { 152 dispatch_async([GCDHelper gcdGlobalQueue:GlobalQueuePriorityDefault], ^{ 153 blockAsyn(); 154 dispatch_async([GCDHelper gcdMainQueue], ^{ 155 blockM(); 156 }); 157 }); 158 } 159 160 #pragma mark - 161 #pragma mark 队列延迟时间执行方法 162 + (void) gcdPerformBlock:(GCDBlock) block onQueue:(dispatch_queue_t) queue delaySecond:(int64_t) second 163 { 164 dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, second * NSEC_PER_SEC); 165 dispatch_after(popTime, queue, block); 166 } 167 168 #pragma mark - 169 #pragma mark 只执行一次 170 171 + (void) gcdPerformBlockOnce:(GCDBlock) block 172 { 173 static dispatch_once_t onceToken; 174 dispatch_once(&onceToken, block); 175 } 176 177 #pragma mark - 178 #pragma mark 无序并发 179 180 + (void) gcdBatchPerformBlocks:(NSArray *) blockArray finally:(GCDBlock) finallyBlock 181 { 182 [blockArray retain]; 183 184 dispatch_queue_t queue = [GCDHelper gcdGlobalQueue:GlobalQueuePriorityDefault]; 185 dispatch_group_t group = dispatch_group_create(); 186 187 for(GCDBlock block in blockArray) 188 { 189 dispatch_group_async(group, queue, ^{ 190 block(); 191 }); 192 } 193 dispatch_group_wait(group, DISPATCH_TIME_FOREVER); 194 195 dispatch_async([GCDHelper gcdGlobalQueue:GlobalQueuePriorityDefault], ^{ 196 finallyBlock(); 197 }); 198 199 dispatch_release(group); 200 201 [blockArray release]; 202 } 203 204 + (void) gcdBatchPerformBlockWithData:(NSArray *) dataArray 205 maxConcurrentOperationCount:(uint) count 206 handleBlock:(GCDBlock1_Obj) block 207 finally:(GCDBlock1_Obj) finallyBlock 208 { 209 [dataArray retain]; 210 211 dispatch_queue_t queue = [GCDHelper gcdGlobalQueue:GlobalQueuePriorityDefault]; 212 dispatch_group_t group = dispatch_group_create(); 213 dispatch_semaphore_t semaphore = dispatch_semaphore_create(count); 214 for(id obj in dataArray) 215 { 216 NSLog(@"并发中"); 217 dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); 218 dispatch_group_async(group, queue, ^{ 219 block(obj); 220 dispatch_semaphore_signal(semaphore); 221 }); 222 } 223 224 dispatch_group_wait(group, DISPATCH_TIME_FOREVER); 225 dispatch_group_notify(group, queue, ^{ 226 finallyBlock(dataArray); 227 }); 228 dispatch_release(group); 229 230 [dataArray release]; 231 } 232 233 234 235 #pragma mark - 236 #pragma mark 图片下载 237 238 - (void) gcdImageWithURLString:(NSString *) URLString 239 { 240 [self gcdImageWithURLString:URLString completion:nil]; 241 } 242 243 - (void) gcdImageWithURLString:(NSString *) URLString completion:(GCDBlock2_Obj_Obj) completion 244 { 245 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 246 247 NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; 248 [request setURL:[NSURL URLWithString:URLString]]; 249 [request setHTTPMethod:@"GET"]; 250 NSData *returnData = [NSURLConnection sendSynchronousRequest:request 251 returningResponse:nil 252 error:nil]; 253 [request release]; 254 255 UIImage *image = [UIImage imageWithData:returnData]; 256 257 if (image) 258 { 259 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 260 completion(image, URLString); 261 }); 262 } else 263 { 264 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 265 completion(image, URLString); 266 }); 267 } 268 }); 269 } 270 271 @end 272 273 274 #pragma mark - 275 #pragma mark 网络部分 276 277 @implementation GCDHelper (NetworkConnect) 278 279 - (BOOL)isReachableWithFlags:(SCNetworkReachabilityFlags)flags 280 { 281 BOOL connectionUP = YES; 282 283 if(!(flags & kSCNetworkReachabilityFlagsReachable)) 284 connectionUP = NO; 285 286 if( (flags & (kSCNetworkReachabilityFlagsConnectionRequired | kSCNetworkReachabilityFlagsTransientConnection)) == (kSCNetworkReachabilityFlagsConnectionRequired | kSCNetworkReachabilityFlagsTransientConnection) ) 287 connectionUP = NO; 288 289 return connectionUP; 290 } 291 292 -(void)reachabilityChanged:(SCNetworkReachabilityFlags)flags 293 { 294 dispatch_async(dispatch_get_main_queue(), ^{ 295 _netWorkBlock([self isReachableWithFlags:flags]); 296 }); 297 } 298 299 static void TMReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info) 300 { 301 @autoreleasepool 302 { 303 [(GCDHelper *)info reachabilityChanged:flags]; 304 } 305 } 306 307 - (void) gcdNetWorkGuarder:(NSString *) hostname withBlock:(GCDBlock1_Bool) block 308 { 309 _netWorkBlock = block; 310 311 SCNetworkReachabilityRef ref = SCNetworkReachabilityCreateWithName(NULL, [hostname UTF8String]); 312 SCNetworkReachabilityContext context = { 0, NULL, NULL, NULL, NULL }; 313 dispatch_queue_t queue = dispatch_queue_create("com.myself.reachability", NULL); 314 context.info = (void *)self; 315 SCNetworkReachabilitySetCallback(ref, TMReachabilityCallback, &context); 316 SCNetworkReachabilitySetDispatchQueue(ref, queue); 317 } 318 319 @end 320 321 @implementation GCDHelper(HttpRequest) 322 323 - (void) startPOSTHTTPRequest:(NSString *) URLString 324 params:(NSDictionary *) params 325 timeout:(NSTimeInterval) time 326 success:(GCDHttpRequestBlock) successBlock 327 fail:(GCDHttpRequestBlock) failBlock 328 { 329 [params retain]; 330 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 331 332 __block NSURLResponse *response = nil; 333 __block NSError *error = nil; 334 __block NSData *receiveData = nil; 335 336 NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; 337 338 [request setURL:[NSURL URLWithString:[URLString lowercaseString]]]; 339 [request setHTTPMethod:@"POST"]; 340 [request setCachePolicy:NSURLRequestUseProtocolCachePolicy]; 341 [request setTimeoutInterval:time]; 342 343 if (!request) 344 { 345 NSDictionary *errorInfo = [NSDictionary dictionaryWithObjectsAndKeys:@"发送请求失败", @"errorKey", nil]; 346 error = [NSError errorWithDomain:@"www.myself.com" code:100 userInfo:errorInfo]; 347 348 dispatch_async(dispatch_get_main_queue(), ^{ 349 successBlock(response, error, receiveData); 350 }); 351 352 return; 353 } 354 355 if (params != nil) 356 { 357 [request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@", BOUNDRY] 358 forHTTPHeaderField:@"Content-Type"]; 359 360 int len=512; 361 NSMutableData *postData =[NSMutableData dataWithCapacity:len]; 362 [postData appendData:[[NSString stringWithFormat:@"--%@/r/n", BOUNDRY] 363 dataUsingEncoding:NSUTF8StringEncoding]]; 364 int i=0; 365 int cnt = [params count]; 366 367 for (NSString *key in [params allKeys]) 368 { 369 // NSString *str = [NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"/r/n/r/n", key]; 370 [postData appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"/r/n/r/n", key] dataUsingEncoding:NSUTF8StringEncoding]]; 371 372 [postData appendData: [[NSString stringWithFormat:@"%@",[params objectForKey:key]] 373 dataUsingEncoding:NSUTF8StringEncoding]]; 374 if(i != cnt - 1) 375 { 376 [postData appendData:[[NSString stringWithFormat:@"/r/n--%@/r/n", BOUNDRY] 377 dataUsingEncoding:NSUTF8StringEncoding]]; 378 } 379 i++ ; 380 } 381 [postData appendData:[[NSString stringWithFormat:@"/r/n--%@--/r/n", BOUNDRY] 382 dataUsingEncoding:NSUTF8StringEncoding]]; 383 384 [request setHTTPBody:postData]; 385 } 386 387 receiveData = [[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error] retain]; 388 if (!error) 389 { 390 dispatch_async(dispatch_get_main_queue(), ^{ 391 successBlock(response, nil, receiveData); 392 }); 393 } 394 else 395 { 396 dispatch_async(dispatch_get_main_queue(), ^{ 397 successBlock(response, error, receiveData); 398 }); 399 } 400 401 [request release]; 402 }); 403 404 [params release]; 405 } 406 407 - (void) startGETHTTPRequest:(NSString *) URLString 408 params:(NSDictionary *) params 409 timeout:(NSTimeInterval) time 410 success:(GCDHttpRequestBlock) successBlock 411 fail:(GCDHttpRequestBlock) failBlock 412 { 413 [params retain]; 414 415 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 416 __block NSURLResponse *response = nil; 417 __block NSError *error = nil; 418 __block NSData *receiveData = nil; 419 420 NSMutableString *paramsString = [[NSMutableString alloc] init]; 421 for(NSString *key in params) 422 { 423 [paramsString appendFormat:@"&%@=%@", key, [params objectForKey:key]]; 424 } 425 NSString *requestString = [[NSString alloc] initWithFormat:@"%@%@", URLString, paramsString]; 426 NSURL *reqUrl = [[NSURL alloc] initWithString:requestString]; 427 428 [paramsString release]; 429 [requestString release]; 430 431 NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; 432 433 [request setURL:reqUrl]; 434 [request setHTTPMethod:@"GET"]; 435 [request setCachePolicy:NSURLRequestUseProtocolCachePolicy]; 436 [request setTimeoutInterval:time]; 437 438 [reqUrl release]; 439 440 if (request) 441 { 442 receiveData = [[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error] retain]; 443 } 444 445 if (!error) 446 { 447 dispatch_async(dispatch_get_main_queue(), ^{ 448 successBlock(response, nil, receiveData); 449 }); 450 } 451 else 452 { 453 dispatch_async(dispatch_get_main_queue(), ^{ 454 successBlock(response, error, receiveData); 455 }); 456 } 457 458 [request release]; 459 }); 460 461 [params release]; 462 } 463 464 - (void) gcdHttpRequestWithURL:(NSString *) URLString 465 httpMethod:(GCDHelperHttpRequestMethod) method 466 params:(NSDictionary *) params 467 timeout:(NSTimeInterval) time 468 success:(GCDHttpRequestBlock) successBlock 469 fail:(GCDHttpRequestBlock) failBlock 470 { 471 switch (method) 472 { 473 case GCDHelperHttpRequestMethodGET: 474 { 475 [self startGETHTTPRequest:URLString params:params timeout:time success:successBlock fail:failBlock]; 476 break; 477 } 478 case GCDHelperHttpRequestMethodPOST: 479 { 480 [self startPOSTHTTPRequest:URLString params:params timeout:time success:successBlock fail:failBlock]; 481 break; 482 } 483 484 default: 485 break; 486 } 487 } 488 489 @end
一、基本概念举例:
1 [cpp] view plaincopyprint? 2 3 #import <UIKit/UIKit.h> 4 5 @interface BaseViewController : UIViewController 6 { 7 IBOutlet UITextField *field1; 8 IBOutlet UITextField *field2; 9 IBOutlet UITextField *field3; 10 11 IBOutlet UITextField *textField; 12 13 dispatch_queue_t queue; 14 } 15 16 - (IBAction) calculate:(id)sender; 17 - (IBAction) operationQueue:(id)sender; 18 - (IBAction) gcd:(id)sender; 19 20 - (IBAction) notchoke:(id)sender; 21 - (IBAction) choke:(id)sender; 22 23 - (IBAction) getUIData:(id)sender; 24 25 26 - (IBAction)startQueue:(id)sender; 27 - (IBAction)suspendQueue:(id)sender; 28 - (IBAction)resumeQueue:(id)sender; 29 30 @end 31 32 33 [cpp] view plaincopyprint? 34 35 #import "BaseViewController.h" 36 37 @implementation BaseViewController 38 39 - (void) dealloc 40 { 41 dispatch_release(queue); 42 43 [super dealloc]; 44 } 45 46 - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 47 { 48 self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 49 if (self) { 50 queue = dispatch_queue_create("sss", NULL); 51 } 52 return self; 53 } 54 55 - (void)viewDidLoad 56 { 57 [super viewDidLoad]; 58 // Do any additional setup after loading the view from its nib. 59 } 60 61 - (void) longTask:(id) sender 62 { 63 NSMutableArray *arr = [NSMutableArray array]; 64 for (int i = 0; i < 1000; i++) { 65 66 [arr addObject:[NSMutableArray arrayWithObject:@(i)]]; 67 NSLog(@"longTask:%d", i); 68 } 69 } 70 71 - (void) longTaskOther:(id) sender 72 { 73 NSMutableArray *arr = [NSMutableArray array]; 74 for (int i = 0; i < 10000; i++) { 75 76 [arr addObject:[NSMutableArray arrayWithObject:@(i)]]; 77 NSLog(@"longTaskOther:%d", i); 78 } 79 } 80 81 - (IBAction) calculate:(id)sender 82 { 83 field3.text = [NSString stringWithFormat:@"%f", [field1.text floatValue] - [field2.text floatValue]]; 84 } 85 - (IBAction) operationQueue:(id)sender; 86 { 87 NSOperationQueue *aqueue = [NSOperationQueue new]; 88 NSInvocationOperation *operation = [[NSInvocationOperation alloc] 89 initWithTarget:self 90 selector:@selector(longTask:) 91 object:nil]; 92 NSInvocationOperation *operation1 = [[NSInvocationOperation alloc] 93 initWithTarget:self 94 selector:@selector(longTaskOther:) 95 object:nil]; 96 97 98 [aqueue addOperation:operation]; 99 [aqueue addOperation:operation1]; 100 101 [operation release]; 102 [operation1 release]; 103 } 104 - (IBAction) gcd:(id)sender //3.192999 105 { 106 [GCDHelper gcdPerformBlockAsynchronous:^{ 107 NSMutableArray *arr = [NSMutableArray array]; 108 for (int i = 0; i < 1000; i++) { 109 110 [arr addObject:[NSMutableArray arrayWithObject:@(i)]]; 111 NSLog(@"longTask:%d", i); 112 } 113 }]; 114 115 [GCDHelper gcdPerformBlockAsynchronous:^{ 116 NSMutableArray *arr = [NSMutableArray array]; 117 for (int i = 0; i < 10000; i++) { 118 119 [arr addObject:[NSMutableArray arrayWithObject:@(i)]]; 120 NSLog(@"longTaskOther:%d", i); 121 } 122 }]; 123 } 124 125 ////////////////////////////////////////////////////// 126 127 - (IBAction)notchoke:(id)sender 128 { 129 dispatch_async(dispatch_get_main_queue(), ^{ 130 NSLog(@"qqq"); 131 }); 132 133 NSLog(@"不阻塞"); 134 } 135 136 137 //Calls to dispatch_sync() targeting the current queue will result 138 //* in dead-lock. Use of dispatch_sync() is also subject to the same 139 //* multi-party dead-lock problems that may result from the use of a mutex. 140 //* Use of dispatch_async() is preferred. 141 //在当前队列上调用dispatch_sync() 会导致死锁。调用dispatch_sync(),并使用mutex 经常会导致多方死锁问题。 142 - (IBAction) choke:(id)sender 143 { 144 dispatch_queue_t exampleQueue; 145 146 int i = 3; 147 switch (i) { 148 case 0: 149 exampleQueue = dispatch_get_global_queue(0, 0); 150 break; 151 case 1: 152 exampleQueue = dispatch_queue_create("com.abc.xxx", NULL); 153 break; 154 case 2: 155 exampleQueue = dispatch_get_current_queue(); 156 break; 157 case 3: 158 exampleQueue = dispatch_get_main_queue(); 159 break; 160 161 default: 162 exampleQueue = dispatch_get_global_queue(0, 0); 163 break; 164 } 165 166 dispatch_sync( exampleQueue,^{ 167 [self longTask:nil]; 168 }); 169 170 NSLog(@"task finish"); 171 } 172 173 - (IBAction) getUIData:(id)sender 174 { 175 dispatch_async(dispatch_get_global_queue(0, 0), ^{ 176 177 __block NSString *stringValue; 178 dispatch_sync(dispatch_get_main_queue(), ^{ 179 stringValue = [textField.text copy]; 180 }); 181 182 [stringValue retain]; 183 184 NSLog(@"stringValue:%@", stringValue); 185 }); 186 } 187 188 189 190 //一个要注意的地方是,dispatch queue的挂起是block粒度的。换句话说,挂起一个queue并不会将当前正在执行的block挂起。它会允许当前执行的block执行完毕,然后后续的block不再会被执行,直至queue被恢复。 191 //还有一个注意点:从man页上得来的:如果你挂起了一个queue或者source,那么销毁它之前,必须先对其进行恢复。 192 - (IBAction)startQueue:(id)sender 193 { 194 dispatch_async(queue, ^{ 195 for (int i = 0; i < 10000; i++) { 196 NSLog(@"taskA"); 197 } 198 }); 199 200 dispatch_async(queue, ^{ 201 for (int i = 0; i < 10000; i++) { 202 NSLog(@"taskB"); 203 } 204 }); 205 206 dispatch_async(queue, ^{ 207 for (int i = 0; i < 10000; i++) { 208 NSLog(@"taskC"); 209 } 210 }); 211 } 212 - (IBAction)suspendQueue:(id)sender 213 { 214 NSLog(@"Queue suspend"); 215 dispatch_suspend(queue); 216 217 } 218 - (IBAction)resumeQueue:(id)sender 219 { 220 NSLog(@"Queue resume"); 221 dispatch_resume(queue); 222 223 }
二、基本用法举例
例子1:
1 #import <UIKit/UIKit.h> 2 3 @interface OneViewController : UIViewController 4 5 6 //无序并发 7 - (IBAction)selector0:(id)sender; 8 9 //无序并发处理数据 10 - (IBAction)selector100:(id)sender; 11 12 //执行一次 13 - (IBAction)selector1:(id)sender; 14 15 //异步/后台执行 16 - (IBAction)selector2:(id)sender; 17 18 //后台执行,然后返回主线程 19 - (IBAction)selector3:(id)sender; 20 21 //三种队列执行 22 - (IBAction)selector4:(UISegmentedControl *)sender; 23 24 //延迟执行 25 - (IBAction)selector5:(id)sender; 26 27 @end 28 29 30 [cpp] view plaincopyprint? 31 32 #import "OneViewController.h" 33 34 @interface OneViewController () 35 36 @end 37 38 @implementation OneViewController 39 40 - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 41 { 42 self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 43 if (self) { 44 // Custom initialization 45 } 46 return self; 47 } 48 49 - (void)viewDidLoad 50 { 51 [super viewDidLoad]; 52 } 53 54 - (NSMutableArray *) getBlockArray 55 { 56 NSMutableArray *arr = [[NSMutableArray array] retain]; 57 58 GCDBlock b0 = ^{ NSLog(@"无序并发: 0"); sleep(3); }; [arr addObject:b0]; 59 GCDBlock b1 = ^{ NSLog(@"无序并发: 1"); }; [arr addObject:b1]; 60 GCDBlock b2 = ^{ NSLog(@"无序并发: 2"); }; [arr addObject:b2]; 61 GCDBlock b3 = ^{ NSLog(@"无序并发: 3"); }; [arr addObject:b3]; 62 GCDBlock b4 = ^{ NSLog(@"无序并发: 4"); }; [arr addObject:b4]; 63 GCDBlock b5 = ^{ NSLog(@"无序并发: 5"); }; [arr addObject:b5]; 64 GCDBlock b6 = ^{ NSLog(@"无序并发: 6"); }; [arr addObject:b6]; 65 GCDBlock b7 = ^{ NSLog(@"无序并发: 7"); }; [arr addObject:b7]; 66 GCDBlock b8 = ^{ NSLog(@"无序并发: 8"); }; [arr addObject:b8]; 67 GCDBlock b9 = ^{ NSLog(@"无序并发: 9"); }; [arr addObject:b9]; 68 GCDBlock b10 = ^{ NSLog(@"无序并发: 10"); }; [arr addObject:b10]; 69 GCDBlock b11 = ^{ NSLog(@"无序并发: 11"); }; [arr addObject:b11]; 70 GCDBlock b12 = ^{ NSLog(@"无序并发: 12"); }; [arr addObject:b12]; 71 GCDBlock b13 = ^{ NSLog(@"无序并发: 13"); }; [arr addObject:b13]; 72 GCDBlock b14 = ^{ NSLog(@"无序并发: 14"); }; [arr addObject:b14]; 73 GCDBlock b15 = ^{ NSLog(@"无序并发: 15"); }; [arr addObject:b15]; 74 75 return arr; 76 } 77 78 //无序并发 79 - (IBAction)selector0:(id)sender 80 { 81 [GCDHelper gcdBatchPerformBlocks:[self getBlockArray] finally:^{ 82 NSLog(@"一组有序并发完成"); 83 }]; 84 85 // NSLog(@"一组无序并发完成"); 86 } 87 88 89 - (IBAction)selector100:(id)sender 90 { 91 NSMutableArray *arr = [NSMutableArray array]; 92 for (int i = 0; i < 100; i++) { 93 [arr addObject:[NSMutableArray array]]; 94 } 95 96 __block int i = 0; 97 [GCDHelper gcdBatchPerformBlockWithData:arr maxConcurrentOperationCount:10 handleBlock:^(id object) { 98 99 sleep(1); 100 NSMutableArray *arr = (NSMutableArray *)object; 101 [arr addObject:@(i)]; 102 i++; 103 } finally:^(id object) { 104 NSLog(@"arr:%@", object); 105 }]; 106 } 107 108 - (IBAction)selector1:(id)sender 109 { 110 [GCDHelper gcdPerformBlockOnce:^{ 111 NSLog(@"别想让我执行第二次"); 112 }]; 113 NSLog(@"不执行~"); 114 } 115 116 //异步/后台执行 117 - (IBAction)selector2:(id)sender 118 { 119 [GCDHelper gcdPerformBlockAsynchronous:^{ 120 sleep(3); 121 NSLog(@"全局队列执行完成"); 122 }]; 123 NSLog(@"全局队列执行,不影响主队列"); 124 } 125 126 //后台执行,然后返回主线程 127 - (IBAction)selector3:(id)sender 128 { 129 [GCDHelper gcdPerformBlockAsynchronous:^{ 130 131 for (int i = 0; i< 10; i++) 132 { 133 NSLog(@"全局队列执行: %d", i); 134 } 135 136 } finishOnMainQueue:^{ 137 NSLog(@"回到主队列"); 138 }]; 139 } 140 141 //三种队列执行 142 - (IBAction)selector4:(UISegmentedControl *)sender 143 { 144 switch (sender.selectedSegmentIndex) { 145 case 0: 146 { 147 [GCDHelper gcdPerformBlockOnMainQueue:^{ 148 NSLog(@"主队列执行"); 149 } feature:PerformBlockFeatureUnchoke]; 150 break; 151 } 152 case 1: 153 { 154 [GCDHelper gcdPerformBlockOnGlobalQueue:^{ 155 NSLog(@"全局队列执行"); 156 } feature:PerformBlockFeatureUnchoke priority:GlobalQueuePriorityDefault]; 157 break; 158 } 159 case 2: 160 { 161 [GCDHelper gcdPerformBlockOnCustomQueue:^{ 162 NSLog(@"自创建队列执行"); 163 } feature:PerformBlockFeatureUnchoke name:@"com.abc.bcd"]; 164 break; 165 } 166 167 default: 168 break; 169 } 170 } 171 172 //延迟执行 173 - (IBAction)selector5:(id)sender 174 { 175 NSLog(@"延迟 2s 执行"); 176 [GCDHelper gcdPerformBlock:^{ 177 NSLog(@"执行完毕"); 178 } onQueue:[GCDHelper gcdMainQueue] delaySecond:2]; 179 } 180 181 @end
1 #import <UIKit/UIKit.h> 2 3 @interface MulthreadConcurrentVC : UIViewController 4 5 6 @end 7 8 9 [cpp] view plaincopyprint? 10 11 #import "MulthreadConcurrentVC.h" 12 13 /* 14 15 如何在GCD中快速的控制并发呢?答案就是 16 dispatch_semaphore,对经常做unix开发的人来讲,我所介绍的内容可能就显得非常入门级了,信号量在他们的多线程开发中再平常不过了。 17 在GCD中有三个函数是semaphore的操作,分别是: 18 dispatch_semaphore_create 创建一个semaphore 19 dispatch_semaphore_signal 发送一个信号 20 dispatch_semaphore_wait 等待信号 21 简单的介绍一下这三个函数,第一个函数有一个整形的参数,我们可以理解为信号的总量,dispatch_semaphore_signal是发送一个信号,自然会让信号总量加1,dispatch_semaphore_wait等待信号,当信号总量少于0的时候就会一直等待,否则就可以正常的执行,并让信号总量减少1,根据这样的原理,我们便可以快速的创建一个并发控制。 22 23 */ 24 25 26 /* 27 28 简单的介绍一下这一段代码,创建了一个初使值为10的semaphore,每一次for循环都会创建一个新的线程,线程结束的时候会发送一个信号,线程创建之前会信号等待,所以当同时创建了10个线程之后,for循环就会阻塞,等待有线程结束之后会增加一个信号才继续执行,如此就形成了对并发的控制,如上就是一个并发数为10的一个线程队列。 29 30 */ 31 32 @implementation MulthreadConcurrentVC 33 34 - (void) loadView 35 { 36 [super loadView]; 37 } 38 39 - (void)aSelector:(id)sender 40 { 41 dispatch_group_t group = dispatch_group_create(); 42 dispatch_semaphore_t semaphore = dispatch_semaphore_create(10); 43 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 44 for (int i = 0; i < 100; i++) 45 { 46 dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); 47 dispatch_group_async(group, queue, ^{ 48 NSLog(@"%i",i); 49 sleep(2); 50 dispatch_semaphore_signal(semaphore); 51 }); 52 } 53 dispatch_group_wait(group, DISPATCH_TIME_FOREVER); 54 dispatch_release(group); 55 dispatch_release(semaphore); 56 } 57 58 - (void)viewDidLoad 59 { 60 [super viewDidLoad]; 61 62 UIButton *bt = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 63 bt.frame = CGRectMake(100, 100, 120, 120); 64 [bt addTarget:self action:@selector(aSelector:) forControlEvents:UIControlEventTouchUpInside]; 65 [self.view addSubview:bt]; 66 }
三、GCD实际应用举例
1 #import <UIKit/UIKit.h> 2 3 #import "GCDHelper.h" 4 5 @interface TableViewController : UITableViewController 6 7 @end 8 9 10 [cpp] view plaincopyprint? 11 12 #import "TableViewController.h" 13 #import "CustomCell.h" 14 #import <objc/runtime.h> 15 16 static char * const kIndexPathAssociationKey = "JK_indexPath"; 17 18 @interface TableViewController () 19 20 @end 21 22 @implementation TableViewController 23 24 - (id)initWithStyle:(UITableViewStyle)style 25 { 26 self = [super initWithStyle:style]; 27 if (self) { 28 // Custom initialization 29 } 30 return self; 31 } 32 33 - (void)viewDidLoad 34 { 35 [super viewDidLoad]; 36 37 self.clearsSelectionOnViewWillAppear = NO; 38 self.navigationItem.rightBarButtonItem = self.editButtonItem; 39 } 40 41 - (void)didReceiveMemoryWarning 42 { 43 [super didReceiveMemoryWarning]; 44 // Dispose of any resources that can be recreated. 45 } 46 47 #pragma mark - Table view data source 48 49 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 50 { 51 return 1; 52 } 53 54 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 55 { 56 return 100; 57 } 58 59 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 60 { 61 static NSString *CellIdentifier = @"Cell"; 62 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 63 64 if (cell == nil) { 65 cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; 66 UIImageView *im = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 40)]; 67 im.tag = 10; 68 [cell addSubview:im]; 69 [im release]; 70 } 71 72 return cell; 73 } 74 75 - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath 76 { 77 // http://localhost:8888/Imgs/img0.png 78 // http://theme.blogcn.com/wp-content/themes/coffee-desk/images/rsscoffee.PNG 79 80 NSString *imgURLStr = nil; 81 if ((indexPath.row % 2) == 0) 82 { 83 imgURLStr = @"http://localhost:8888/Imgs/img0.png"; 84 } else 85 { 86 imgURLStr = @"http://localhost:8888/Imgs/img1.png"; 87 } 88 89 GCDHelper *hp = [GCDHelper new]; 90 [hp gcdImageWithURLString:imgURLStr 91 completion:^(id object1, id object2) { 92 93 dispatch_async(dispatch_get_main_queue(), ^{ 94 UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath]; 95 [(UIImageView *)[cell viewWithTag:10] setImage:(UIImage *)object1]; 96 }); 97 }]; 98 } 99 100 #pragma mark - Table view delegate 101 102 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 103 { 104 } 105 106 #pragma mark - 107 #pragma mark - cell重用 108 109 - (void)tableViewCellIsPreparingForReuse:(NSNotification *)notification 110 { 111 if ([[notification object] isKindOfClass:[CustomCell class]]) { 112 CustomCell *cell = (CustomCell *)[notification object]; 113 114 objc_setAssociatedObject(cell, 115 kIndexPathAssociationKey, 116 nil, 117 OBJC_ASSOCIATION_RETAIN); 118 119 [[cell imageView] setImage:nil]; 120 } 121 } 122 123 @end
1 #import <UIKit/UIKit.h> 2 3 extern NSString * const kJKPrepareForReuseNotification; 4 5 @interface CustomCell : UITableViewCell 6 7 @end 8 9 10 [cpp] view plaincopyprint? 11 12 #import "CustomCell.h" 13 14 NSString * const kJKPrepareForReuseNotification = @"JKCallbacksTableViewCell_PrepareForReuse"; 15 16 @implementation CustomCell 17 18 - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier 19 { 20 self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; 21 if (self) { 22 //如果cell 的图片发生改变,当cell重用的时候,刷新图片 23 24 [[self imageView] addObserver:self 25 forKeyPath:@"image" 26 options:NSKeyValueObservingOptionOld 27 context:NULL]; 28 } 29 return self; 30 } 31 32 - (void)observeValueForKeyPath:(NSString *)keyPath 33 ofObject:(id)object 34 change:(NSDictionary *)change 35 context:(void *)context 36 { 37 NSLog(@"observeValueForKeyPath"); 38 39 if (object == [self imageView] && 40 [keyPath isEqualToString:@"image"] && 41 ([change objectForKey:NSKeyValueChangeOldKey] == nil || 42 [change objectForKey:NSKeyValueChangeOldKey] == [NSNull null])) 43 { 44 [self setNeedsLayout]; 45 } 46 } 47 48 - (void)prepareForReuse 49 { 50 [[NSNotificationCenter defaultCenter] postNotificationName:kJKPrepareForReuseNotification 51 object:self]; 52 53 [super prepareForReuse]; 54 } 55
1 #import <Foundation/Foundation.h> 2 3 @interface NetGuarder : NSObject 4 5 + (NetGuarder *) shareNetGuarder; 6 7 @end
1 #import "NetGuarder.h" 2 3 @implementation NetGuarder 4 5 static NetGuarder *guarder = nil; 6 7 + (void) getNetConnectMsg 8 { 9 GCDHelper *hp = [GCDHelper new]; 10 [hp gcdNetWorkGuarder:@"www.baidu.com" withBlock:^(BOOL flag) { 11 if (flag) 12 { 13 NSLog(@"Net connect"); 14 } else 15 { 16 NSLog(@"Net not connect"); 17 } 18 }]; 19 } 20 21 + (NetGuarder *) shareNetGuarder 22 { 23 static dispatch_once_t predicate; 24 dispatch_once(&predicate, ^{ 25 26 NSLog(@"单例创建"); 27 guarder = [[self alloc] init]; 28 29 [NetGuarder getNetConnectMsg]; 30 }); 31 32 return guarder; 33 } 34 35 @end
1 #import <UIKit/UIKit.h> 2 3 @interface URLConViewController : UIViewController <NSURLConnectionDataDelegate> 4 { 5 IBOutlet UISegmentedControl *segment; 6 IBOutlet UILabel *label; 7 } 8 9 @end
1 #import "URLConViewController.h" 2 3 typedef struct _INT 4 { 5 int t1; 6 7 }INT_STRUCT; 8 9 @interface URLConViewController () 10 { 11 NSMutableData *receivedData; 12 BOOL finished; 13 } 14 15 @end 16 17 @implementation URLConViewController 18 19 - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 20 { 21 self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 22 if (self) 23 { 24 receivedData = [[NSMutableData data] retain]; 25 } 26 return self; 27 } 28 29 - (void)viewDidLoad 30 { 31 [super viewDidLoad]; 32 } 33 34 - (void)didReceiveMemoryWarning 35 { 36 [super didReceiveMemoryWarning]; 37 } 38 39 - (void) cleanText 40 { 41 label.text = @""; 42 } 43 44 - (IBAction)segmentAction:(UISegmentedControl *)sender 45 { 46 switch (sender.selectedSegmentIndex) { 47 case 0: 48 { 49 [self sendRequestSync]; 50 break; 51 } 52 case 1: 53 { 54 [self sendRequestAsync]; 55 break; 56 } 57 case 2: 58 { 59 [self sendRequestAsyncOther]; 60 break; 61 } 62 case 3: 63 { 64 [self gcdRequest]; 65 break; 66 } 67 68 default: 69 break; 70 } 71 } 72 73 #pragma mark - 74 #pragma mark GCDRequest 75 76 - (void) gcdRequest 77 { 78 GCDHelper *hp = [GCDHelper new]; 79 80 [hp gcdHttpRequestWithURL:@"http://localhost:8888/test.php" 81 httpMethod:GCDHelperHttpRequestMethodGET 82 params:[NSDictionary dictionary] 83 timeout:5.0f 84 success:^(NSURLResponse *response, NSError *error, NSData *data) { 85 if (data && (!error)) 86 { 87 label.text = [[data objectFromJSONData] description]; 88 } 89 90 } 91 fail:^(NSURLResponse *response, NSError *error, NSData *data) { 92 if (error) 93 { 94 label.text = [error description]; 95 } 96 }]; 97 } 98 99 #pragma mark - 100 #pragma mark sendRequestSync 101 102 - (void) sendRequestSync 103 { 104 [self cleanText]; 105 106 NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; 107 108 [request setURL:[NSURL URLWithString:@"http://localhost:8888/test.php"]]; 109 [request setHTTPMethod:@"GET"]; 110 111 NSError *error = nil; 112 NSData *data = [NSURLConnection sendSynchronousRequest:request 113 returningResponse:nil 114 error:&error]; 115 116 if (data && (!error)) 117 { 118 label.text = [[data objectFromJSONData] description]; 119 } 120 } 121 122 #pragma mark - 123 #pragma mark sendRequestAsync 124 125 - (void) sendRequestAsync 126 { 127 finished = NO; 128 129 NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; 130 [request setURL:[NSURL URLWithString:@"http://localhost:8888/test1.php"]]; 131 [request setHTTPMethod:@"GET"]; 132 [request setCachePolicy:NSURLRequestUseProtocolCachePolicy]; 133 [request setTimeoutInterval:5.0f]; 134 135 NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request 136 delegate:self 137 startImmediately:YES]; 138 139 [connection start]; 140 141 // 但是异步模式下带来了一个新的问题,很多情况下,网络请求不在主线程,或者界面等待网络结果,不在主线程的时候,调用线程如果生命周期over,下面这些可能都没有调用到,导致得不到想要得效果,所以需要在NSURLConnection请求后面加点东西来阻塞 142 while(!finished) { 143 144 [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; 145 146 } 147 } 148 149 // 收到回应 150 - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response 151 { 152 // 注意这里将NSURLResponse对象转换成NSHTTPURLResponse对象才能去 153 NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response; 154 155 if ([response respondsToSelector:@selector(allHeaderFields)]) 156 { 157 NSDictionary *dictionary = [httpResponse allHeaderFields]; 158 NSLog(@"allHeaderFields: %@",dictionary); 159 } 160 [receivedData setLength:0]; 161 } 162 163 // 接收数据 164 - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 165 { 166 NSLog(@"get some data"); 167 [receivedData appendData:data]; 168 } 169 170 // 数据接收完毕 171 - (void)connectionDidFinishLoading:(NSURLConnection *)connection 172 { 173 NSString *results = [[NSString alloc] initWithBytes:[receivedData bytes] 174 length:[receivedData length] 175 encoding:NSUTF8StringEncoding]; 176 177 label.text = [[results objectFromJSONString] description]; 178 179 finished = YES; 180 } 181 182 // 返回错误 183 -(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 184 { 185 NSLog(@"Connection failed: %@", error); 186 } 187 188 #pragma mark - 189 #pragma mark sendRequestAsyncOther 190 191 - (IBAction) sendRequestAsyncOther 192 { 193 [self cleanText]; 194 195 NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; 196 [request setURL:[NSURL URLWithString:@"http://localhost:8888/test2.php"]]; 197 [request setHTTPMethod:@"GET"]; 198 [request setCachePolicy:NSURLRequestUseProtocolCachePolicy]; 199 [request setTimeoutInterval:5.0f]; 200 201 [NSURLConnection sendAsynchronousRequest:request 202 queue:[NSOperationQueue new] 203 completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { 204 205 dispatch_async(dispatch_get_main_queue(), ^{ 206 label.text = [[data objectFromJSONData] description]; 207 }); 208 209 }]; 210 } 211 212 @end
1 #import <Foundation/Foundation.h> 2 3 /** Simple GCD-based timer based on NSTimer. 4 5 Starts immediately and stops when deallocated. This avoids many of the typical problems with NSTimer: 6 7 * RNTimer runs in all modes (unlike NSTimer) 8 * RNTimer runs when there is no runloop (unlike NSTimer) 9 * Repeating RNTimers can easily avoid retain loops (unlike NSTimer) 10 */ 11 12 @interface RNTimer : NSObject 13 14 /**--------------------------------------------------------------------------------------- 15 @name Creating a Timer 16 ----------------------------------------------------------------------------------------- 17 */ 18 19 /** Creates and returns a new repeating RNTimer object and starts running it 20 21 After `seconds` seconds have elapsed, the timer fires, executing the block. 22 You will generally need to use a weakSelf pointer to avoid a retain loop. 23 The timer is attached to the main GCD queue. 24 25 @param seconds The number of seconds between firings of the timer. Must be greater than 0. 26 @param block Block to execute. Must be non-nil 27 28 @return A new RNTimer object, configured according to the specified parameters. 29 */ 30 + (RNTimer *)repeatingTimerWithTimeInterval:(NSTimeInterval)seconds block:(dispatch_block_t)block; 31 32 33 /**--------------------------------------------------------------------------------------- 34 @name Firing a Timer 35 ----------------------------------------------------------------------------------------- 36 */ 37 38 /** Causes the block to be executed. 39 40 This does not modify the timer. It will still fire on schedule. 41 */ 42 - (void)fire; 43 44 45 /**--------------------------------------------------------------------------------------- 46 @name Stopping a Timer 47 ----------------------------------------------------------------------------------------- 48 */ 49 50 /** Stops the receiver from ever firing again 51 52 Once invalidated, a timer cannot be reused. 53 54 */ 55 - (void)invalidate; 56 @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
若发现有不合适或错误之处,还请批评指正,不胜感激。
握不住的沙,干脆扬了它。