封装思想之:NSoperation的自定义实现

一 NSoperase自定义封装实现

[以下代码实现来MJ]

实现过程:通过对NSOperation进行自定义的封装,实现自己的功能,这里使用tableView的cell 更新来实现 图片刷新异步操作,节约系统资源优化代码

其中NSOperasion实现先在主线程调用 并添加队列实现异步的操作并在自定义NSOperation中对图片进行加载,完了通过代理实现 返回主线程 进行赋值

一:自定义封装NSOperation

[.h文件实现] HMDownloadOperation.h

该文件主要确定了自定义的需要的数据信息 用于外部接口使用

 1 #import <Foundation/Foundation.h>
 2 
 3 @class HMDownloadOperation;
 4 
 5 @protocol HMDownloadOperationDelegate <NSObject>
 6 @optional
 7 - (void)downloadOperation:(HMDownloadOperation *)operation didFinishDownload:(UIImage *)image;
 8 @end
 9 
10 @interface HMDownloadOperation : NSOperation
11 @property (nonatomic, copy) NSString *url;//用于记录网页中的图片地址
12 @property (nonatomic, strong) NSIndexPath *indexPath;//用来记录cell,当回调时候获取当前要刷新的cell 绑定cell
13 @property (nonatomic, weak) id<HMDownloadOperationDelegate> delegate;
14 @end
View Code

[.m文件实现]

在对NSOperation进行封装的时候,m文件必须是现在此操作 实现main函数功能用于实现异步下载,并通过

 dispatch_async(dispatch_get_main_queue(), ^{});返回主线程 并刷新UI

 1 #import "HMDownloadOperation.h"
 2 
 3 @implementation HMDownloadOperation
 4 
 5 /**
 6  *  在main方法中实现具体操作
 7  */
 8 - (void)main
 9 {
10     @autoreleasepool {
11         
12         NSURL *downloadUrl = [NSURL URLWithString:self.url];
13         NSData *data = [NSData dataWithContentsOfURL:downloadUrl]; // 这行会比较耗时
14         UIImage *image = [UIImage imageWithData:data];
15 
16         if ([self.delegate respondsToSelector:@selector(downloadOperation:didFinishDownload:)]) {
17             dispatch_async(dispatch_get_main_queue(), ^{ // 回到主线程, 传递图片数据给代理对象
18                 [self.delegate downloadOperation:self didFinishDownload:image];
19             });
20         }
21     }
22 }
23 @end
View Code

以下是控制器实现实现【重在实现思路】,tableView刷新cell 将图片的更新与自定义NSOperation相结合,

控制器.m文件的实现

  1 #import "HMApp.h"
  2 #import "HMViewController.h"
  3 #import "HMDownloadOperation.h"
  4 
  5 @interface HMViewController () <HMDownloadOperationDelegate>
  6 @property (nonatomic, strong) NSArray *apps; //用来存储数据结构Model
  7 @property (nonatomic, strong) NSOperationQueue *queue;//用来全局控制自定义NSOperasion的队列
  8 /** key:url value:operation对象 */
  9 @property (nonatomic, strong) NSMutableDictionary *operations;
 10 //这里定义一个字典类的操作,是为了实现每一个Cell的Operation与网页中的url地址进行绑定,定义她的字典主要是为了考虑图片正在下载而没有加载到images的情况
 11 /** key:url value:image对象*/
 12 @property (nonatomic, strong) NSMutableDictionary *images;
 13 //cell中操作的赋值实现,如果对cell进行封装应该都也cell封装类里面
 14 @end
 15 
 16 @implementation HMViewController
 17 
 18 - (NSArray *)apps
 19 {
 20     if (!_apps) {
 21         NSArray *dictArray = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"apps.plist" ofType:nil]];
 22         
 23         NSMutableArray *appArray = [NSMutableArray array];
 24         for (NSDictionary *dict in dictArray) {
 25             HMApp *app = [HMApp appWithDict:dict];
 26             [appArray addObject:app];
 27         }
 28         _apps = appArray;
 29     }
 30     return _apps;
 31 }
 32 
 33 - (NSOperationQueue *)queue
 34 {
 35     if (!_queue) {
 36         _queue = [[NSOperationQueue alloc] init];
 37         _queue.maxConcurrentOperationCount = 3; // 最大并发数 == 3
 38     }
 39     return _queue;
 40 }
 41 
 42 - (NSMutableDictionary *)operations
 43 {
 44     if (!_operations) {
 45         _operations = [NSMutableDictionary dictionary];
 46     }
 47     return _operations;
 48 }
 49 
 50 - (NSMutableDictionary *)images
 51 {
 52     if (!_images) {
 53         _images = [NSMutableDictionary dictionary];
 54     }
 55     return _images;
 56 }
 57 
 58 - (void)viewDidLoad
 59 {
 60     [super viewDidLoad];
 61     
 62 }
 63 
 64 #pragma mark - 数据源方法
 65 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
 66 {
 67     return self.apps.count;
 68 }
 69 
 70 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
 71 {
 72     static NSString *ID = @"app";
 73     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
 74     if (!cell) {
 75         cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
 76     }
 77     
 78     HMApp *app = self.apps[indexPath.row];
 79     cell.textLabel.text = app.name;
 80     cell.detailTextLabel.text = app.download;
 81     
 82     // 显示图片
 83     // 保证一个url对应一个HMDownloadOperation
 84     // 保证一个url对应UIImage对象
 85     
 86     UIImage *image = self.images[app.icon];
 87     if (image) { // 缓存中有图片
 88         cell.imageView.image = image;
 89     } else { // 缓存中没有图片, 得下载
 90         cell.imageView.image = [UIImage imageNamed:@"57437179_42489b0"];
 91         
 92         HMDownloadOperation *operation = self.operations[app.icon];
 93         if (operation) { // 正在下载
 94             // ... 暂时不需要做其他事
 95             
 96         } else { // 没有正在下载
 97             // 创建操作
 98             operation = [[HMDownloadOperation alloc] init];
 99             operation.url = app.icon;
100             operation.delegate = self;
101             operation.indexPath = indexPath;
102             [self.queue addOperation:operation]; // 异步下载
103             
104             self.operations[app.icon] = operation;
105         }
106     }
107     
108     // SDWebImage : 专门用来下载图片
109     return cell;
110 }
111 
112 #pragma mark - HMDownloadOperationDelegate
113 - (void)downloadOperation:(HMDownloadOperation *)operation didFinishDownload:(UIImage *)image
114 {
115     // 1.移除执行完毕的操作
116     [self.operations removeObjectForKey:operation.url];
117     
118     if (image) {
119         // 2.将图片放到缓存中(images)
120         self.images[operation.url] = image;
121         
122         // 3.刷新表格
123         [self.tableView reloadRowsAtIndexPaths:@[operation.indexPath] withRowAnimation:UITableViewRowAnimationNone];
124         
125         // 3.将图片写入沙盒
126 //        NSData *data = UIImagePNGRepresentation(image);
127 //        [data writeToFile:@"" atomically:<#(BOOL)#>];
128     }
129     
130 }
131 
132 - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
133 {
134     // 开始拖拽
135     // 暂停队列
136     [self.queue setSuspended:YES];
137 }
138 
139 - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
140 {
141     [self.queue setSuspended:NO];
142 }
143 
144 @end
控制器代码实现
原文地址:https://www.cnblogs.com/caolongs/p/4816860.html