• 自定义NSOperation下载图片


    自定义NSOperation的话,只是需要将要下载图片的操作下载它的main方法里面,考虑到,图片下载完毕,需要回传到控制器里,这里可以采用block,也可以采用代理的方式实现,我采用的是代理的方式实现的。

    重点应该是如何避免同一个url的图片被重复下载?!事实上,可以有这样两个字典,key值是图片的url,value的话,一个字典可以是当前的operation对象,表示,这个url对应的图片正在下载,如果传入图片的url,value不为空的话,说明图片正在下载,那么就不需要再重复下载。另一个字典,可以是存放下载好的图片,也就是常说的缓存,如果一个url取出来的value不为nil,那么这张图片就存在缓存中,不需要再次下载。当然,别忘了设置占位图片~~

    这是model的代码:

    #import <Foundation/Foundation.h>
    
    @interface ZYApp : NSObject
    @property (nonatomic, copy) NSString *name;
    @property (nonatomic, copy) NSString *icon;
    @property (nonatomic, copy) NSString *download;
    
    + (id)appWithDict:(NSDictionary *)dict;
    - (id)initWithDict:(NSDictionary *)dict;
    @end
    
    
    #import "ZYApp.h"
    
    @implementation ZYApp
    
    - (id)initWithDict:(NSDictionary *)dict
    {
        if (self = [super init]){
            [self setValuesForKeysWithDictionary:dict];
    //        NSLog(@"%@----%@---%@",self.icon,self.name,self.download);
        }
        return self;
    }
    
    + (id)appWithDict:(NSDictionary *)dict
    {
        return [[self alloc] initWithDict:dict];
    }
    @end
    

     这是自定义的Operation代码:

    #import <Foundation/Foundation.h>
    #import <UIKit/UIKit.h>
    @class ZYDownLoadImageOperation;
    
    @protocol ZYDownLoadImageOperationDelegate <NSObject>
    @optional
    - (void)DownLoadImageOperation:(ZYDownLoadImageOperation *)operation didFinishDownLoadImage:(UIImage *)image;
    @end
    @interface ZYDownLoadImageOperation : NSOperation
    @property (nonatomic, weak) id<ZYDownLoadImageOperationDelegate> delegate;
    @property (nonatomic, copy) NSString *url;
    @property (nonatomic, strong) NSIndexPath *indexPath;
    @end
    
    #import "ZYDownLoadImageOperation.h"
    
    @implementation ZYDownLoadImageOperation
    - (void)main   //重写main方法即可
    {
        @autoreleasepool {    //在子线程中,并不会自动添加自动释放池,所以,手动添加,免得MARC的情况下,出现内存泄露的问题
            NSURL *DownLoadUrl = [NSURL URLWithString:self.url];
            if (self.isCancelled) return;          //如果下载操作被取消,那么就无需下面操作了
            NSData *data = [NSData dataWithContentsOfURL:DownLoadUrl];
            if (self.isCancelled) return;
            UIImage *image = [UIImage imageWithData:data];
            if (self.isCancelled) return;
            
            if ([self.delegate respondsToSelector:@selector(DownLoadImageOperation:didFinishDownLoadImage:)]) {
                dispatch_async(dispatch_get_main_queue(), ^{   //回到主线程,更新UI
                    [self.delegate DownLoadImageOperation:self didFinishDownLoadImage:image];
                });
            }
        }
    }
    @end
    

     这是控制器代码:

    #import <UIKit/UIKit.h>
    
    @interface ViewController : UIViewController
    
    @end
    
    #import "ViewController.h"
    #import "ZYApp.h"
    #import "ZYDownLoadImageOperation.h"
    
    @interface ViewController () <UITableViewDataSource, UITableViewDelegate, ZYDownLoadImageOperationDelegate, UIScrollViewDelegate>
    @property (weak, nonatomic) IBOutlet UITableView *tableView;
    
    @property (nonatomic, strong) NSArray *apps;
    
    @property (nonatomic, strong) NSOperationQueue *queue;
    
    //  key:图片的url  values: 相对应的operation对象  (判断该operation下载操作是否正在执行,当同一个url地址的图片正在下载,那么不需要再次下载,以免重复下载,当下载操作执行完,需要移除)
    @property (nonatomic, strong) NSMutableDictionary *operations;
    
    //  key:图片的url  values: 相对应的图片        (缓存,当下载操作完成,需要将所下载的图片放到缓存中,以免同一个url地址的图片重复下载)
    @property (nonatomic, strong) NSMutableDictionary *images;
    @end
    
    @implementation ViewController
    
    #define ZYCellIdentifier  @"ZYCellIdentifier"
    - (NSArray *)apps
    {
        if (_apps == nil) {
            NSArray *dictArray = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"apps.plist" ofType:nil]];
            NSMutableArray *tmpArray = [NSMutableArray array];
            for (NSDictionary *dict in dictArray) {
                ZYApp *app = [ZYApp appWithDict:dict];
                [tmpArray addObject:app];
            }
            _apps = tmpArray;
        }
        return _apps;
    }
    
    - (NSOperationQueue *)queue
    {
        if (_queue == nil) {
            _queue = [[NSOperationQueue alloc] init];
            _queue.maxConcurrentOperationCount = 3;
        }
        return _queue;
    }
    
    - (NSMutableDictionary *)operations
    {
        if (_operations == nil) {
            _operations = [NSMutableDictionary dictionary];
        }
        return _operations;
    }
    
    - (NSMutableDictionary *)images
    {
        if (_images == nil) {
            _images = [NSMutableDictionary dictionary];
        }
        return _images;
    }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        [self setupView];
    }
    
    - (void)setupView
    {
        self.tableView.delegate = self;
        self.tableView.dataSource = self;
    }
    
    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
    {
        return 1;
    }
    
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
        return self.apps.count;
    }
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ZYCellIdentifier];
        if (cell == nil) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ZYCellIdentifier];
        }
        ZYApp *app = self.apps[indexPath.row];
        cell.textLabel.text = app.name;
        cell.detailTextLabel.text = app.download;
        UIImage *image = self.images[app.icon];
        if (image) {
            cell.imageView.image = image;
        }
        else{
            cell.imageView.image = [UIImage imageNamed:@"TestMam"];
            ZYDownLoadImageOperation *operation = self.operations[app.icon];
            if (operation) {  //正在下载(可以在里面取消下载)
                
            }
            else{ //没有在下载
                operation = [[ZYDownLoadImageOperation alloc] init];
                operation.delegate = self;
                operation.url = app.icon;
                operation.indexPath = indexPath;
                [self.queue addOperation:operation];  //异步下载
                
                self.operations[app.icon] = operation;  //加入字典,表示正在执行此次操作
            }
        }
        return cell;
    }
    
    #pragma mark -- ZYDownLoadImageOperationDelegate
    - (void)DownLoadImageOperation:(ZYDownLoadImageOperation *)operation didFinishDownLoadImage:(UIImage *)image
    {
        [self.operations removeObjectForKey:operation.url];    //下载操作完成,所以把它清掉,表示没有正在下载
        
        if (image){
            self.images[operation.url] = image;    //下载完毕,放入缓存,免得重复下载
            
            [self.tableView reloadRowsAtIndexPaths:@[operation.indexPath] withRowAnimation:UITableViewRowAnimationNone];
        }
        
    }
    
    #pragma mark --- UIScrollViewDelegate
    - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
    {
        [self.queue setSuspended:YES];    //在拖拽的时候,停止队列下载
    }
    
    - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
    {
        [self.queue setSuspended:NO];    //在停止拖拽的时候,开始队列下载
    }
    @end
    

     这是此次mode代码github地址:https://github.com/wzpziyi1/CustomOperation

  • 相关阅读:
    P1361 小M的作物 【网络流】【最小割】
    餐巾计划问题 【网络流24题】【费用流】【zkw】
    P1231 教辅的组成 【网络流】【最大流】
    Rikka with coin 思维题
    线段树模板新
    AC自动机 洛谷P3966 单词
    AC自动机 洛谷P5357 模板
    AC自动机 洛谷P3796
    AC自动机 洛谷P3808 模板
    KMP 洛谷P3375
  • 原文地址:https://www.cnblogs.com/ziyi--caolu/p/4672536.html
Copyright © 2020-2023  润新知