一 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
控制器代码实现