本文介绍: 一 概述将NSBlockOperation封装自定义Operation文件图片下载放到自定义Operation文件main方法下载后回到主线程image图片显示,通过代理完成二 自定义NSOperation2.1 自定义NSOperation步骤简单重写-(void)main方法,在俩面实现执行任务2.2 重写-(void)main的方法的注意点自己创建自动释放池,因为如果是异步操作,无法访问线程自动释放池经常通过-(BOOL)isCancelled方法检测

概述

自定义NSOperation

2.1 自定义NSOperation的步骤简单

重写-(void)main方法,在俩面实现执行的任务

2.2 重写-(void)main的方法的注意点

自定义NSOperation

3.1 DownloadOperation

DownloadOperation.h
#import <Foundation/Foundation.h&gt;
#import <UIKit/UIKit.h>

@class DownloadOperation;
@protocol ILDownloadOperationDelegate<NSObject>

@optional
-(void)downloadOperation:(DownloadOperation *)operation didFinishDownload:(UIImage *)image andIndexPath:(NSIndexPath *)indexPath;

@end

@interface DownloadOperation : NSOperation

@property(nonatomic,copy) NSString *imageUrl;
@property(nonatomic,strong) NSIndexPath *indexPath;
@property(nonatomic,weak) id<ILDownloadOperationDelegate> delegate;

@end
DownloadOperation.m
#import "DownloadOperation.h"
@implementation DownloadOperation
- (void)main
{
    @autoreleasepool {
        if (self.isCancelled) return; //下载前判断是否取消下载
        
        NSURL *url=[NSURL URLWithString:self.imageUrl];
        NSData *data=[NSData dataWithContentsOfURL:url];
        UIImage *image=[UIImage imageWithData:data];
        
        if (self.isCancelled) return; //判断下载过程中
        //回到主线程
        [[NSOperationQueue mainQueue]addOperationWithBlock:^{
            if ([self.delegate respondsToSelector:@selector(downloadOperation:didFinishDownload:andIndexPath:)]) {
                [self.delegate downloadOperation:self didFinishDownload:image andIndexPath:self.indexPath];
            }
            
        }];
    }
}
@end

3.2 App

App.h
#import <Foundation/Foundation.h>

@interface App : NSObject
@property(nonatomic,copy) NSString *name;
@property(nonatomic,copy) NSString *download;
@property(nonatomic,copy) NSString *icon;

+(instancetype)appWithDict:(NSDictionary *)dict;

@end
App.m
#import "App.h"

@implementation App

+(instancetype)appWithDict:(NSDictionary *)dict
{
    App *app=[[self alloc]init];
    [app setValuesForKeysWithDictionary:dict];
    return app;
}
@end

3.3 ILAppsViewController

#define APPImageFile(url) [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)lastObject] stringByAppendingPathComponent:[url lastPathComponent]]
#import "ILAppsViewController.h"
#import "App.h"
#import "DownloadOperation.h"

@interface ILAppsViewController ()<ILDownloadOperationDelegate>
//存放数据
@property(nonatomic,strong) NSMutableArray *apps;
//存放所有下载操作队列
@property(nonatomic,strong) NSOperationQueue *queue;
//存放所有的下载操作(urlkey,operation是value)
@property(nonatomic,strong) NSMutableDictionary *operations;
//存放所有下载完的图片
@property(nonatomic,strong) NSMutableDictionary *images;

@end

@implementation ILAppsViewController

#pragma mark-懒加载代码

-(NSMutableArray *)apps
{
    if (!_apps) {
        NSMutableArray *appArray=[NSMutableArray array];
        //加载plist
        NSString *file=[[NSBundle mainBundle]pathForResource:@"apps" ofType:@"plist"];
        NSArray *dicctArray=[NSArray arrayWithContentsOfFile:file];
        
        //2-字典模型
        for(NSDictionary *dict in dicctArray){
            App *app=[App appWithDict:dict];
            [appArray addObject:app];
        }
        //3.赋值
        self.apps=appArray;
    }
    return _apps;
}
-(NSOperationQueue *)queue
{
    if (!_queue) {
        self.queue=[[NSOperationQueue alloc]init];
    }
    return _queue;
}
-(NSMutableDictionary *)operations
{
    if (!_operations) {
        self.operations=[[NSMutableDictionary alloc]init];
    }
    return _operations;
}
- (NSMutableDictionary *)images
{
    if (!_images) {
        self.images=[[NSMutableDictionary alloc]init];
    }
    return _images;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
}

-(void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    //移除下载操作
    [self.queue cancelAllOperations];
    [self.images removeAllObjects];
    [self.operations removeAllObjects];
    
    
}
#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
#warning Incomplete implementation, return the number of sections
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
#warning Incomplete implementation, return the number of rows
    return self.apps.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *ID=@"app";
    
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    if (!cell) {
        cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
    }
    //取出模型
    App *app=self.apps[indexPath.row];
    
    cell.textLabel.text=app.name;
    cell.detailTextLabel.text=app.download;
    //方法四-先从images缓存取出url对应的UIImage对象
    UIImage *image=self.images[app.icon];
    if (image) { //说明图片已经下载成功
        cell.imageView.image=image;
        //NSLog(@"----从缓存中取得图片---%d",indexPath.row);
    }else{ //说明图片并未下载成功过(并未缓存过)
       
        NSString *file=APPImageFile(app.icon);
        //先从沙盒中取出文件
        NSData *data=[NSData dataWithContentsOfFile:file];
        if (data) {//沙盒中存在这个文件
            cell.imageView.image=[UIImage imageWithData:data];
        }else{ //沙盒中不存在这个文件
            
            //NSLog(@"----缓存中没有图片---%d",indexPath.row);
            //显示占位图片
            cell.imageView.image=[UIImage imageNamed:@"placeholder"];
            //下载图片
            [self download:app.icon indexPath:indexPath];
        }
    }
    return cell;
}
-(void)download:(NSString *)imageUrl indexPath:(NSIndexPath *)indexPath{
    //取出当前图片url对应的下载操作(operation对象)
    DownloadOperation *operation=self.operations[imageUrl];
    if (operation) return;
    operation=[[DownloadOperation alloc]init];
    operation.imageUrl=imageUrl;
    operation.indexPath=indexPath;
    //设置代理
    operation.delegate=self;
    //添加操作到队列
    [self.queue addOperation:operation];
    //添加字典中(为了解决重复下载)
    self.operations[imageUrl]=operation;
}
//当用户开始拖拽表格调用开始拖拽
//1-会阻塞主线程,影响用户体验
//2-重复下载,浪费流量,浪费时间影响用户体验
//保证:1张图片只下载1次
-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    //暂停下载
    [self.queue setSuspended:YES];
}
//当用户停止拖表格拽时
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    //恢复下载
    [self.queue setSuspended:NO];
    
}
-(void)downloadOperation:(DownloadOperation *)operation didFinishDownload:(UIImage *)image andIndexPath:(nonnull NSIndexPath *)indexPath
{
    //存放图片到字典中
    if(image){
        //self.images[imageUrl]=image;
        self.images[operation.imageUrl]=image;//循环引用换成weak
        //将图片存入沙盒中:UIImage->Data——>File
        NSData *data=UIImagePNGRepresentation(image);
        [data writeToFile:APPImageFile(operation.imageUrl) atomically:YES];
        
    }
    //从字典中移除下载操作
    [self.operations removeObjectForKey:operation.imageUrl];
    //刷新表格
    //[self.tableView reloadData];
    [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];//刷新一行
}

@end

3.4 效果图

原文地址:https://blog.csdn.net/Calvin_zhou/article/details/123296726

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。

如若转载,请注明出处:http://www.7code.cn/show_11711.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注