IOS 自定义Operation(下载功能)

一个下载操作就交给一个HMDownloadOperation对象

HMDownloadOperation.h / .m

@class HMDownloadOperation;

@protocol HMDownloadOperationDelegate <NSObject>
@optional
- (void)downloadOperation:(HMDownloadOperation *)operation didFinishDownload:(UIImage *)image;
@end

@interface HMDownloadOperation : NSOperation
@property (nonatomic, copy) NSString *url;
@property (nonatomic, strong) NSIndexPath *indexPath;
@property (nonatomic, weak) id<HMDownloadOperationDelegate> delegate;
@end

#import "HMDownloadOperation.h"

@implementation HMDownloadOperation

/**
 *  在main方法中实现具体操作
 */
- (void)main
{
    @autoreleasepool {

        NSURL *downloadUrl = [NSURL URLWithString:self.url];
        NSData *data = [NSData dataWithContentsOfURL:downloadUrl]; // 这行会比较耗时
        UIImage *image = [UIImage imageWithData:data];

        if ([self.delegate respondsToSelector:@selector(downloadOperation:didFinishDownload:)]) {
            dispatch_async(dispatch_get_main_queue(), ^{ // 回到主线程, 传递图片数据给代理对象
                [self.delegate downloadOperation:self didFinishDownload:image];
            });
        }
    }
}

控制器View 调用

@interface HMViewController () <HMDownloadOperationDelegate>
@property (nonatomic, strong) NSArray *apps;
@property (nonatomic, strong) NSOperationQueue *queue;
/** key:url value:operation对象 */
@property (nonatomic, strong) NSMutableDictionary *operations;

/** key:url value:image对象*/
@property (nonatomic, strong) NSMutableDictionary *images;
@end

@implementation HMViewController

- (NSArray *)apps
{
    if (!_apps) {
        NSArray *dictArray = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"apps.plist" ofType:nil]];

        NSMutableArray *appArray = [NSMutableArray array];
        for (NSDictionary *dict in dictArray) {
            HMApp *app = [HMApp appWithDict:dict];
            [appArray addObject:app];
        }
        _apps = appArray;
    }
    return _apps;
}

- (NSOperationQueue *)queue
{
    if (!_queue) {
        _queue = [[NSOperationQueue alloc] init];
        _queue.maxConcurrentOperationCount = 3; // 最大并发数 == 3
    }
    return _queue;
}

- (NSMutableDictionary *)operations
{
    if (!_operations) {
        _operations = [NSMutableDictionary dictionary];
    }
    return _operations;
}

- (NSMutableDictionary *)images
{
    if (!_images) {
        _images = [NSMutableDictionary dictionary];
    }
    return _images;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

}

#pragma mark - 数据源方法
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    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];
    }

    HMApp *app = self.apps[indexPath.row];
    cell.textLabel.text = app.name;
    cell.detailTextLabel.text = app.download;

    // 显示图片
    // 保证一个url对应一个HMDownloadOperation
    // 保证一个url对应UIImage对象

    UIImage *image = self.images[app.icon];
    if (image) { // 缓存中有图片
        cell.imageView.image = image;
    } else { // 缓存中没有图片, 得下载
        cell.imageView.image = [UIImage imageNamed:@"57437179_42489b0"];

        HMDownloadOperation *operation = self.operations[app.icon];
        if (operation) { // 正在下载
            // ... 暂时不需要做其他事

        } else { // 没有正在下载
            // 创建操作
            operation = [[HMDownloadOperation alloc] init];
            operation.url = app.icon;
            operation.delegate = self;
            operation.indexPath = indexPath;
            [self.queue addOperation:operation]; // 异步下载

            self.operations[app.icon] = operation;
        }
    }

    // SDWebImage : 专门用来下载图片
    return cell;
}

#pragma mark - HMDownloadOperationDelegate
- (void)downloadOperation:(HMDownloadOperation *)operation didFinishDownload:(UIImage *)image
{
    // 1.移除执行完毕的操作
    [self.operations removeObjectForKey:operation.url];

    if (image) {
        // 2.将图片放到缓存中(images)
        self.images[operation.url] = image;

        // 3.刷新表格
        [self.tableView reloadRowsAtIndexPaths:@[operation.indexPath] withRowAnimation:UITableViewRowAnimationNone];

        // 3.将图片写入沙盒
//        NSData *data = UIImagePNGRepresentation(image);
//        [data writeToFile:@"" atomically:<#(BOOL)#>];
    }

}

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    // 开始拖拽
    // 暂停队列
    [self.queue setSuspended:YES];
}

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
{
    [self.queue setSuspended:NO];
}

@end
时间: 2025-01-18 05:38:20

IOS 自定义Operation(下载功能)的相关文章

iOS多线程自定义operation加载图片 不重复下载图片

摘要:1:ios通过抽象类NSOperation封装了gcd,让ios的多线程变得更为简单易用:   2:耗时的操作交给子线程来完成,主线程负责ui的处理,提示用户的体验   2:自定义operation继承自NSOperation,在子线程中下载图片: 3:保证图片只下载一次,还有保证下载任务不重复 ------------------------------------------------------------------------------------ 实现原理:1:图片缓存:用

iOS开发 -文件下载(5 下载功能的封装)

iOS开发网络篇—文件下载(五·下载功能的封装) 一.简单说明 在前面几篇文章介绍下载代码的基础上,此文分析对下载功能进行封装. 通过之前的代码,我们发现仅仅是下载一个文件就需要写很长的代码,那么如果要下载多个文件,就需要写多份代码.在这里,我们把下载一个文件的代码进行封装.控制器只需要知道,下载哪个文件,下载到哪个路径就可以了. 在对下载的功能进行封装后,添加一个文件下载器,一个文件下载器只下载一个文件,封装后如果要下载多个文件的话,那么只需要创建多个文件下载器对象就可以进行控制和下载了. 二

iOS开发中文件的上传和下载功能的基本实现-备用

感谢大神分享 这篇文章主要介绍了iOS开发中文件的上传和下载功能的基本实现,并且下载方面讲到了大文件的多线程断点下载,需要的朋友可以参考下 文件的上传 说明:文件上传使用的时POST请求,通常把要上传的数据保存在请求体中.本文介绍如何不借助第三方框架实现iOS开发中得文件上传. 由于过程较为复杂,因此本文只贴出部分关键代码. 主控制器的关键代码: 复制代码代码如下: YYViewController.m#import "YYViewController.h" #define YYEnc

iOS开发网络篇—文件下载(五&#183;下载功能的封装)

iOS开发网络篇—文件下载(五·下载功能的封装) 一.简单说明 在前面几篇文章介绍下载代码的基础上,此文分析对下载功能进行封装. 通过之前的代码,我们发现仅仅是下载一个文件就需要写很长的代码,那么如果要下载多个文件,就需要写多份代码.在这里,我们把下载一个文件的代码进行封装.控制器只需要知道,下载哪个文件,下载到哪个路径就可以了. 在对下载的功能进行封装后,添加一个文件下载器,一个文件下载器只下载一个文件,封装后如果要下载多个文件的话,那么只需要创建多个文件下载器对象就可以进行控制和下载了. 二

ios开发视频播放后台下载功能实现 :1,ios播放视频 ,包含基于AVPlayer播放器,2,实现下载,iOS后台下载(多任务同时下载,单任务下载,下载进度,下载百分比,文件大小,下载状态)(真机调试功能正常)

ABBPlayerKit ios开发视频播放后台下载功能实现 : 代码下载地址:https://github.com/niexiaobo/ABBPlayerKit github资料学习和下载地址:https://github.com/niexiaobo/ 实现功能 :播放视频 ,视频后台下载 (真机调试功能正常) 1.使用ZFPlayer播放视频(可以在线和本地播放,基于AVPlayer,调节音量和屏幕亮度) 2.使用 WHCNetWorkKit 实现下载,后台下载(多任务同时下载,单任务下载,

iOS彩票项目--第五天,新特性引导页的封装、返回按钮的自定义、导航控制器的滑动返回以及自定义滑动返回功能

一.上次实现了在AppDelegate中通过判断app版本决定是否进入新特性页面,今天将AppDelegate中的一坨进行了封装.将self.window的根控制器到底应该为新特性界面,还是主页面,封装到了导航工具类ChaosGuideTool 封装,先决定外面怎么用,然后实现方法.外部通过类方法调用  + (UIViewController *)chooseRootVC; 外部的APPDelegate 只是调用方法 之前的业务判断没有改变,只是将数据的存储进行了封装 二.返回按钮的自定义 <1

iOS自定义转场动画实战讲解

iOS自定义转场动画实战讲解 转场动画这事,说简单也简单,可以通过presentViewController:animated:completion:和dismissViewControllerAnimated:completion:这一组函数以模态视图的方式展现.隐藏视图.如果用到了navigationController,还可以调用pushViewController:animated:和popViewController这一组函数将新的视图控制器压栈.弹栈. 下图中所有转场动画都是自定义的

Objective-c下具有下载功能的NSURLCache类CustomURLCache

最近在做iOS APP开发的过程中遇到了这么一个问题:我开发的是一个阅读类的App,正文界面是通过UIWebViewController来实现的,现在要实现文章离线阅读功能.即将当前web页面所有的资源请求结果都下载都本地.在网上找了很多方法,发现都不是很好.后来还是决定从cache入手:iOS自带的NSURLCache并不支持将cache下载到自定义的目录底下,所以只有复写NSURLCache这个类来实现这些功能.在网上找到一个他人写的CustomURLCache的类,但是发现使用的过程中程序

Android开发本地及网络Mp3音乐播放器(十五)网络音乐及歌词下载功能实现

实现功能: 实现网络音乐歌词下载功能(下载音乐的同时,下载对应歌词) 下载好的歌词目前不在播放器内,可以通过文件浏览器查看. 后续将博文,将实现本地音乐歌词下载和已下载音乐扫描功能. 因为,没有自己的服务器,所以网络音乐所有相关功能(包含搜索音乐.下载音乐.下载歌词)均无法保证时效性,建议,尽快下载和练习:如果你下载时候,已经因为我采集的服务器更改规则,请给我留言,如果可以解决,我将在有空的时候献上新的源码. 截止到目前的源码下载: http://download.csdn.net/album/