zoukankan      html  css  js  c++  java
  • 封装思想之: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
    控制器代码实现
  • 相关阅读:
    SpringCloud系列二:Restful 基础架构(搭建项目环境、创建 Dept 微服务、客户端调用微服务)
    SpringCloud系列一:SpringCloud的简介和架构
    SpringBoot系列十二:SpringBoot整合 Shiro
    SpringBoot系列十一:SpringBoot整合Restful架构(使用 RestTemplate 模版实现 Rest 服务调用、Swagger 集成、动态修改日志级别)
    SpringBoot系列十:SpringBoot整合Redis
    SpringBoot系列九:SpringBoot服务整合(整合邮件服务、定时调度、Actuator监控)
    SpringBoot系列八:SpringBoot整合消息服务(SpringBoot 整合 ActiveMQ、SpringBoot 整合 RabbitMQ、SpringBoot 整合 Kafka)
    SpringBoot系列七:SpringBoot 整合 MyBatis(配置 druid 数据源、配置 MyBatis、事务控制、druid 监控)
    SpringBoot系列六:SpringBoot整合Tomcat
    SpringBoot系列五:SpringBoot错误处理(数据验证、处理错误页、全局异常)
  • 原文地址:https://www.cnblogs.com/caolongs/p/4816860.html
Copyright © 2011-2022 走看看