iOS开发多线程篇—自定义NSOperation
生活随笔
收集整理的這篇文章主要介紹了
iOS开发多线程篇—自定义NSOperation
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
iOS開發多線程篇—自定義NSOperation
一、實現一個簡單的tableView顯示效果
實現效果展示:
?
代碼示例(使用以前在主控制器中進行業務處理的方式)
1.新建一個項目,讓控制器繼承自UITableViewController。
1 //2 // YYViewController.h3 // 01-自定義Operation4 //5 // Created by apple on 14-6-26.6 // Copyright (c) 2014年 itcase. All rights reserved.7 //8 9 #import <UIKit/UIKit.h> 10 11 @interface YYViewController : UITableViewController 12 13 @end2.處理storyboard中得界面,如下:
3.根據plist文件,字典轉模型
新建一個類,繼承自NSObject,作為數據的模型
YYappModel.h文件
1 //2 // YYappModel.h3 // 01-自定義Operation4 //5 // Created by apple on 14-6-26.6 // Copyright (c) 2014年 itcase. All rights reserved.7 //8 9 #import <Foundation/Foundation.h> 10 11 @interface YYappModel : NSObject 12 /** 13 *應用名稱 14 */ 15 @property(nonatomic,copy)NSString *name; 16 /** 17 * 應用圖片 18 */ 19 @property(nonatomic,copy)NSString *icon; 20 /** 21 * 應用的下載量 22 */ 23 @property(nonatomic,copy)NSString *download; 24 25 +(instancetype)appModelWithDict:(NSDictionary *)dict; 26 -(instancetype)initWithDict:(NSDictionary *)dict; 27 @endYYappModel.m文件
1 //2 // YYappModel.m3 // 01-自定義Operation4 //5 // Created by apple on 14-6-26.6 // Copyright (c) 2014年 itcase. All rights reserved.7 //8 9 #import "YYappModel.h" 10 11 @implementation YYappModel 12 13 -(instancetype)initWithDict:(NSDictionary *)dict 14 { 15 if (self=[super init]) { 16 [self setValuesForKeysWithDictionary:dict]; 17 } 18 return self; 19 } 20 21 //工廠方法 22 +(instancetype)appModelWithDict:(NSDictionary *)dict 23 { 24 return [[self alloc]initWithDict:dict]; 25 } 26 @end主控制器中得邏輯控制部分,YYViewController.m文件
1 //2 // YYViewController.m3 // 01-自定義Operation4 //5 // Created by apple on 14-6-26.6 // Copyright (c) 2014年 itcase. All rights reserved.7 //8 9 #import "YYViewController.h" 10 #import "YYappModel.h" 11 12 @interface YYViewController () 13 @property(nonatomic,strong)NSArray *apps; 14 15 @end 16 17 @implementation YYViewController 18 #pragma mark- 懶加載 19 -(NSArray *)apps 20 { 21 if (_apps==nil) { 22 NSString *path=[[NSBundle mainBundle]pathForResource:@"apps.plist" ofType:nil]; 23 NSArray *tempArray=[NSArray arrayWithContentsOfFile:path]; 24 25 //字典轉模型 26 NSMutableArray *array=[NSMutableArray array]; 27 for (NSDictionary *dict in tempArray) { 28 YYappModel *app=[YYappModel appModelWithDict:dict]; 29 [array addObject:app]; 30 } 31 _apps=array; 32 } 33 return _apps; 34 } 35 36 #pragma mark-數據源方法 37 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 38 { 39 return self.apps.count; 40 } 41 42 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 43 { 44 static NSString *ID=@"ID"; 45 UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:ID]; 46 if (cell==nil) { 47 cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID]; 48 } 49 YYappModel *app=self.apps[indexPath.row]; 50 cell.textLabel.text=app.name; 51 cell.detailTextLabel.text=app.download; 52 53 //下載圖片數據 54 NSLog(@"加載圖片數據---%@", [NSThread currentThread]); 55 NSURL *url=[NSURL URLWithString:app.icon]; 56 NSData *data=[NSData dataWithContentsOfURL:url]; 57 UIImage *imgae=[UIImage imageWithData:data]; 58 cell.imageView.image=imgae; 59 NSLog(@"完成顯示"); 60 return cell; 61 } 62 63 @end打印查看:
二、自定義NSOperation
說明:上面的下載圖片數據部分是一個非常耗時的操作,這個操作任務在主線程完成,會嚴重的影響到用戶體驗,造成UI卡的現象。下面通過自定義NSOperation,新開線程,讓加載圖片的任務異步執行。
1.通過代理
在上面的基礎上,新建一個類,讓其繼承自NSOperation。
YYdownLoadOperation.h文件
1 //2 // YYdownLoadOperation.h3 // 01-自定義Operation4 //5 // Created by apple on 14-6-26.6 // Copyright (c) 2014年 itcase. All rights reserved.7 //8 9 #import <Foundation/Foundation.h> 10 11 #pragma mark-設置代理和代理方法 12 @class YYdownLoadOperation; 13 @protocol YYdownLoadOperationDelegate <NSObject> 14 -(void)downLoadOperation:(YYdownLoadOperation*)operation didFishedDownLoad:(UIImage *)image; 15 @end 16 17 @interface YYdownLoadOperation : NSOperation 18 @property(nonatomic,copy)NSString *url; 19 @property(nonatomic,strong)NSIndexPath *indexPath; 20 @property(nonatomic,strong)id <YYdownLoadOperationDelegate> delegate; 21 @endYYdownLoadOperation.m文件
1 //2 // YYdownLoadOperation.m3 // 01-自定義Operation4 //5 // Created by apple on 14-6-26.6 // Copyright (c) 2014年 itcase. All rights reserved.7 //8 9 #import "YYdownLoadOperation.h" 10 11 @implementation YYdownLoadOperation 12 -(void)main 13 { 14 NSURL *url=[NSURL URLWithString:self.url]; 15 NSData *data=[NSData dataWithContentsOfURL:url]; 16 UIImage *imgae=[UIImage imageWithData:data]; 17 18 NSLog(@"--%@--",[NSThread currentThread]); 19 //圖片下載完畢后,通知代理 20 if ([self.delegate respondsToSelector:@selector(downLoadOperation:didFishedDownLoad:)]) { 21 dispatch_async(dispatch_get_main_queue(), ^{//回到主線程,傳遞數據給代理對象 22 [self.delegate downLoadOperation:self didFishedDownLoad:imgae]; 23 }); 24 } 25 } 26 @end主控制器中的業務邏輯:
1 //2 // YYViewController.m3 // 01-自定義Operation4 //5 // Created by apple on 14-6-26.6 // Copyright (c) 2014年 itcase. All rights reserved.7 //8 9 #import "YYViewController.h" 10 #import "YYappModel.h" 11 #import "YYdownLoadOperation.h" 12 13 @interface YYViewController ()<YYdownLoadOperationDelegate> 14 @property(nonatomic,strong)NSArray *apps; 15 @property(nonatomic,strong)NSOperationQueue *queue; 16 17 @end 18 19 @implementation YYViewController 20 #pragma mark- 懶加載apps 21 -(NSArray *)apps 22 { 23 if (_apps==nil) { 24 NSString *path=[[NSBundle mainBundle]pathForResource:@"apps.plist" ofType:nil]; 25 NSArray *tempArray=[NSArray arrayWithContentsOfFile:path]; 26 27 //字典轉模型 28 NSMutableArray *array=[NSMutableArray array]; 29 for (NSDictionary *dict in tempArray) { 30 YYappModel *app=[YYappModel appModelWithDict:dict]; 31 [array addObject:app]; 32 } 33 _apps=array; 34 } 35 return _apps; 36 } 37 38 #pragma mark-懶加載queue 39 -(NSOperationQueue *)queue 40 { 41 if (_queue==Nil) { 42 _queue=[[NSOperationQueue alloc]init]; 43 //設置最大并發數為3 44 _queue.maxConcurrentOperationCount=3; 45 } 46 return _queue; 47 } 48 49 #pragma mark-數據源方法 50 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 51 { 52 return self.apps.count; 53 } 54 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 55 { 56 static NSString *ID=@"ID"; 57 UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:ID]; 58 if (cell==nil) { 59 cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID]; 60 } 61 YYappModel *app=self.apps[indexPath.row]; 62 cell.textLabel.text=app.name; 63 cell.detailTextLabel.text=app.download; 64 65 //下載圖片數據 66 // NSLog(@"加載圖片數據---%@", [NSThread currentThread]); 67 // NSURL *url=[NSURL URLWithString:app.icon]; 68 // NSData *data=[NSData dataWithContentsOfURL:url]; 69 // UIImage *imgae=[UIImage imageWithData:data]; 70 // cell.imageView.image=imgae; 71 72 //創建一個OPeration對象 73 YYdownLoadOperation *operation=[[YYdownLoadOperation alloc]init]; 74 operation.url=app.icon; 75 operation.indexPath=indexPath; 76 operation.delegate=self; 77 78 //把操作對象添加到隊列中在去 79 [self.queue addOperation:operation]; 80 81 // NSLog(@"完成顯示"); 82 return cell; 83 } 84 -(void)downLoadOperation:(YYdownLoadOperation *)operation didFishedDownLoad:(UIImage *)image 85 { 86 //返回圖片數據給每行對應的cell的imageview.image 87 //取出tableview中indexPath這一行對應的cell 88 UITableViewCell *cell=[self.tableView cellForRowAtIndexPath:operation.indexPath]; 89 //顯示圖片 90 cell.imageView.image=image; 91 // NSLog(@"cell--index--%@---%@",operation.indexPath,[NSThread currentThread]); 92 //一定要刷新表格 93 [self.tableView reloadData]; 94 NSLog(@"--%@--",[NSThread currentThread]); 95 96 } 97 @end說明:通過打印可以發現上面的代碼存在很大的問題。
問題1:需要保證一個url對應一個operation對象。
問題2:下載完需要移除。移除執行完畢的操作。
問題3:保證一個url對應一個image。 下面對主控制器中得代碼進行改進: 1 //2 // YYViewController.m3 // 01-自定義Operation4 //5 // Created by apple on 14-6-26.6 // Copyright (c) 2014年 itcase. All rights reserved.7 //8 9 #import "YYViewController.h"10 #import "YYappModel.h"11 #import "YYdownLoadOperation.h"12 13 @interface YYViewController ()<YYdownLoadOperationDelegate>14 @property(nonatomic,strong)NSArray *apps;15 @property(nonatomic,strong)NSOperationQueue *queue;16 @property(nonatomic,strong)NSMutableDictionary *operations;17 @property(nonatomic,strong)NSMutableDictionary *images;18 19 @end20 21 @implementation YYViewController22 #pragma mark- 懶加載apps23 -(NSArray *)apps24 {25 if (_apps==nil) {26 NSString *path=[[NSBundle mainBundle]pathForResource:@"apps.plist" ofType:nil];27 NSArray *tempArray=[NSArray arrayWithContentsOfFile:path];28 29 //字典轉模型30 NSMutableArray *array=[NSMutableArray array];31 for (NSDictionary *dict in tempArray) {32 YYappModel *app=[YYappModel appModelWithDict:dict];33 [array addObject:app];34 }35 _apps=array;36 }37 return _apps;38 }39 40 #pragma mark-懶加載queue41 -(NSOperationQueue *)queue42 {43 if (_queue==Nil) {44 _queue=[[NSOperationQueue alloc]init];45 //設置最大并發數為346 _queue.maxConcurrentOperationCount=3;47 }48 return _queue;49 }50 51 #pragma mark-懶加載operations52 -(NSMutableDictionary *)operations53 {54 if (_operations==Nil) {55 _operations=[NSMutableDictionary dictionary];56 }57 return _operations;58 }59 60 #pragma mark-懶加載images61 -(NSMutableDictionary *)images62 {63 if (_images==Nil) {64 _images=[NSMutableDictionary dictionary];65 }66 return _images;67 }68 69 #pragma mark-數據源方法70 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section71 {72 return self.apps.count;73 }74 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath75 {76 static NSString *ID=@"ID";77 UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:ID];78 if (cell==nil) {79 cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];80 }81 YYappModel *app=self.apps[indexPath.row];82 cell.textLabel.text=app.name;83 cell.detailTextLabel.text=app.download;84 85 //保證一個url對應一個image對象86 UIImage *image=self.images[app.icon];87 if (image) {//緩存中有圖片88 cell.imageView.image=image;89 }else // 緩存中沒有圖片,得下載90 {91 //先設置一張占位圖片92 cell.imageView.image=[UIImage imageNamed:@"57437179_42489b0"];93 YYdownLoadOperation *operation=self.operations[app.icon];94 if (operation) {//正在下載95 //什么都不做96 }else //當前沒有下載,那就創建操作97 {98 operation=[[YYdownLoadOperation alloc]init];99 operation.url=app.icon; 100 operation.indexPath=indexPath; 101 operation.delegate=self; 102 [self.queue addOperation:operation];//異步下載 103 self.operations[app.icon]=operation; 104 } 105 } 106 107 108 return cell; 109 } 110 -(void)downLoadOperation:(YYdownLoadOperation *)operation didFishedDownLoad:(UIImage *)image 111 { 112 //1.移除執行完畢的操作 113 [self.operations removeObjectForKey:operation.url]; 114 115 //2.將圖片放到緩存中 116 self.images[operation.url]=image; 117 118 //3.刷新表格(只刷新下載的那一行) 119 120 [self.tableView reloadRowsAtIndexPaths:@[operation.indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; 121 NSLog(@"--%d--%@--",operation.indexPath.row,[NSThread currentThread]); 122 123 } 124 @end打印查看:
?
轉載于:https://www.cnblogs.com/187n/p/5056714.html
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的iOS开发多线程篇—自定义NSOperation的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: VS2008资源问题解决方法
- 下一篇: Oracle 数据库连接失败问题