一、基础用法

 //
// ViewController.m
// IOS_0120_NSOperation
//
// Created by ma c on 16/1/20.
// Copyright © 2016年 博文科技. All rights reserved.
// #import "ViewController.h" @interface ViewController ()<UITableViewDelegate> @property (nonatomic, strong) UIImageView *imageView; @end @implementation ViewController
/*
一、简介
1.NSOperation的作用
配合使用NSOperation和NSOperationQueue也能实现多线程编程 2.NSOperation和NSOperationQueue实现多线程的具体步骤
1>先将需要执行的操作封装到一个NSOperation对象中
2>然后将NSOperation对象添加到NSOperationQueue中
3>系统会自动将NSOperationQueue中的NSOperation取出来
4>将取出的NSOperation封装的操作放到一条新线程中执行 二、NSOperation的子类
1.NSOperation是个抽象类,并不具备封装操作的能力,必须使用它的子类 2.使用NSOperation子类的方式有3种
1>NSInvocationOperation
2>NSBlockOperation
3>自定义子类继承NSOperation,实现内部相应的方法 三、具体使用
1.NSInvocationOperation
1>创建NSInvocationOperation对象
- (id)initWithTarget:(id)target selector:(SEL)sel object:(id)arg; 2>调用start方法开始执行操作
- (void)start;
一旦执行操作,就会调用target的sel方法 3>注意
默认情况下,调用了start方法后并不会开一条新线程去执行操作,而是在当前线程同步执行操作
只有将NSOperation放到一个NSOperationQueue中,才会异步执行操作 2.NSBlockOperation
1>创建NSBlockOperation对象
+ (id)blockOperationWithBlock:(void (^)(void))block; 2>通过addExecutionBlock:方法添加更多的操作
- (void)addExecutionBlock:(void (^)(void))block; 3>注意:只要NSBlockOperation封装的操作数 > 1,就会异步执行操作 三、NSOperationQueue
1.NSOperationQueue的作用
NSOperation可以调用start方法来执行任务,但默认是同步执行的
如果将NSOperation添加到NSOperationQueue(操作队列)中,系统会自动异步执行NSOperation中的操作 2.添加操作到NSOperationQueue中
- (void)addOperation:(NSOperation *)op;
- (void)addOperationWithBlock:(void (^)(void))block; 四、最大并发数
1.什么是并发数
同时执行的任务数
比如,同时开3个线程执行3个任务,并发数就是3 2.最大并发数的相关方法
- (NSInteger)maxConcurrentOperationCount;
- (void)setMaxConcurrentOperationCount:(NSInteger)cnt; 五、队列的取消、暂停、恢复
取消队列的所有操作
- (void)cancelAllOperations;
提示:也可以调用NSOperation的- (void)cancel方法取消单个操作 暂停和恢复队列
- (void)setSuspended:(BOOL)b; // YES代表暂停队列,NO代表恢复队列
- (BOOL)isSuspended; 六、操作优先级
1.设置NSOperation在queue中的优先级,可以改变操作的执行优先级
- (NSOperationQueuePriority)queuePriority;
- (void)setQueuePriority:(NSOperationQueuePriority)p; 2.优先级的取值
NSOperationQueuePriorityVeryLow = -8L,
NSOperationQueuePriorityLow = -4L,
NSOperationQueuePriorityNormal = 0,
NSOperationQueuePriorityHigh = 4,
NSOperationQueuePriorityVeryHigh = 8 七、操作的监听
1.可以监听一个操作的执行完毕
- (void (^)(void))completionBlock;
- (void)setCompletionBlock:(void (^)(void))block; 八、操作的依赖
NSOperation之间可以设置依赖来保证执行顺序
比如一定要让操作A执行完后,才能执行操作B,可以这么写
[operationB addDependency:operationA]; // 操作B依赖于操作A
可以在不同queue的NSOperation之间创建依赖关系 注意:不能相互依赖 比如A依赖B,B依赖A 九、第三方框架的使用建议
1.用第三方框架的目的
1> 开发效率:快速开发,人家封装好的一行代码顶自己写的N行
2> 为了使用这个功能最牛逼的实现 2.第三方框架过多,很多坏处(忽略不计)
1> 管理、升级、更新
2> 第三方框架有BUG,等待作者解决
3> 第三方框架的作者不幸去世、停止更新(潜在的BUG无人解决)
4> 感觉:自己好水 3.比如
流媒体:播放在线视频、音频(边下载边播放)
非常了解音频、视频文件的格式
每一种视频都有自己的解码方式(C\C++) 4.总结
1> 站在巨人的肩膀上编程
2> 没有关系,使劲用那么比较稳定的第三方框架 十、SDWebImage
1.什么是SDWebImage
iOS中著名的牛逼的网络图片处理框架
包含的功能:图片下载、图片缓存、下载进度监听、gif处理等等
用法极其简单,功能十分强大,大大提高了网络图片的处理效率
国内超过90%的iOS项目都有它的影子
2.项目地址
https://github.com/rs/SDWebImage 1> 常用方法
- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder;
- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options;
- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletionBlock)completedBlock;
- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock; 2> 内存处理:当app接收到内存警告时
当app接收到内存警告
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application
{
SDWebImageManager *mgr = [SDWebImageManager sharedManager]; // 1.取消正在下载的操作
[mgr cancelAll]; // 2.清除内存缓存
[mgr.imageCache clearMemory];
}
3> SDWebImageOptions
* SDWebImageRetryFailed : 下载失败后,会自动重新下载
* SDWebImageLowPriority : 当正在进行UI交互时,自动暂停内部的一些下载操作
* SDWebImageRetryFailed | SDWebImageLowPriority : 拥有上面2个功能 十一、自定义NSOperation
自定义NSOperation的步骤很简单
重写- (void)main方法,在里面实现想执行的任务 重写- (void)main方法的注意点
自己创建自动释放池(因为如果是异步操作,无法访问主线程的自动释放池)
经常通过- (BOOL)isCancelled方法检测操作是否被取消,对取消做出响应 */ - (void)viewDidLoad {
[super viewDidLoad]; // [self useNSInvocationOperation];
// [self useBaseNSBlockOperation];
// [self useNSBlockOperation];
// [self useNSOperationQueue];
// [self useAddDependency]; self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(, , , )];
[self.view addSubview:self.imageView];
[self communicate]; } #pragma mark - 通讯
- (void)communicate
{
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//取消队列所有操作
// [queue cancelAllOperations];
// NSLog(@"didCancelAllOperations");
//暂停队列
[queue setSuspended:YES];
//恢复队列
[queue setSuspended:NO];
//异步下载图片
[queue addOperationWithBlock:^{
NSURL *url = [NSURL URLWithString:@"http://images.haiwainet.cn/2016/0113/20160113015030150.jpg"];
NSData *data = [[NSData alloc] initWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data];
//回到主线程,显示图片
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
self.imageView.image = image;
}];
}];
} - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
// [queue setSuspended:YES]; //暂停队列中所有任务
} - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
// [queue setSuspended:NO]; //恢复队列中所有任务
} #pragma mark - 依赖
- (void)useAddDependency
{
/*三个异步执行操作:操作C依赖于操作B,操作B依赖于操作A*/ //创建一个队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init]; NSBlockOperation *operationA = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"A1--------%@",[NSThread currentThread]);
}];
[operationA addExecutionBlock:^{
NSLog(@"A2--------%@",[NSThread currentThread]);
}];
[operationA setCompletionBlock:^{
NSLog(@"依赖于A--------%@",[NSThread currentThread]); }];
NSBlockOperation *operationB = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"B--------%@",[NSThread currentThread]);
}];
NSBlockOperation *operationC = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"C--------%@",[NSThread currentThread]);
}];
//设置依赖
[operationB addDependency:operationA];
[operationC addDependency:operationB]; [queue addOperation:operationA];
[queue addOperation:operationB];
[queue addOperation:operationC];
} #pragma mark - 队列中直接添加任务
- (void)useNSOperationQueue
{
//1.创建operation的时候,添加一个任务
NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"--------下载图片1--------%@",[NSThread currentThread]);
}];
NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"--------下载图片2--------%@",[NSThread currentThread]);
}]; //2.创建队列(非主队列)会自动异步执行任务,并发
NSOperationQueue *queue = [[NSOperationQueue alloc] init]; //3.设置最大并发数
queue.maxConcurrentOperationCount = ; //4.添加操作到队列中
[queue addOperation:operation1];
[queue addOperation:operation2]; [queue addOperationWithBlock:^{
NSLog(@"--------下载图片3--------%@",[NSThread currentThread]);
}];
} #pragma mark - 多操作添加到队列
- (void)useNSBlockOperation
{
//创建operation的时候,添加一个任务
NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"--------下载图片1--------%@",[NSThread currentThread]);
}];
NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"--------下载图片2--------%@",[NSThread currentThread]);
}];
//创建队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//主队列
// NSOperationQueue *queue = [NSOperationQueue mainQueue];
//添加操作到队列中
[queue addOperation:operation1];
[queue addOperation:operation2]; //[operation start];
} #pragma mark - NSBlockOperation
- (void)useBaseNSBlockOperation
{
//创建operation的时候,添加一个任务
// NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
// NSLog(@"--------下载图片1--------%@",[NSThread currentThread]);
// }]; NSBlockOperation *operation = [[NSBlockOperation alloc] init];
//操作中添加任务
[operation addExecutionBlock:^{
NSLog(@"--------下载图片2--------%@",[NSThread currentThread]);
}];
[operation addExecutionBlock:^{
NSLog(@"--------下载图片3--------%@",[NSThread currentThread]);
}]; //任务大于1,才会异步执行
[operation start];
} #pragma mark - NSInvocationOperation
- (void)useNSInvocationOperation
{
//创建队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//创建操作
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download) object:nil]; //opreation直接调用start,是同步执行(在当前线程执行操作)
//[operation start]; //添加操作到队列中,会自动异步执行
[queue addOperation:operation];
} - (void)download
{
NSLog(@"download-------%@",[NSThread currentThread]);
} - (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
} @end

二、防止重复下载,与沙盒缓存

 //
// BWApp.h
// IOS_0120_NSOperation防止重复下载
//
// Created by ma c on 16/1/20.
// Copyright © 2016年 博文科技. All rights reserved.
// #import <Foundation/Foundation.h> @interface BWApp : NSObject @property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *download;
@property (nonatomic, copy) NSString *icon; + (instancetype)appWithDict:(NSDictionary *)dict; @end //
// BWApp.m
// IOS_0120_NSOperation防止重复下载
//
// Created by ma c on 16/1/20.
// Copyright © 2016年 博文科技. All rights reserved.
// #import "BWApp.h" @implementation BWApp + (instancetype)appWithDict:(NSDictionary *)dict
{
BWApp *app = [[self alloc] init];
[app setValuesForKeysWithDictionary:dict];
return app;
} @end
 //
// BWTableViewController.m
// IOS_0120_NSOperation防止重复下载
//
// Created by ma c on 16/1/20.
// Copyright © 2016年 博文科技. All rights reserved.
// #import "BWTableViewController.h"
#import "BWApp.h" #define appImageCachesPath(url) [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:[url lastPathComponent]] @interface BWTableViewController () //所有应用数据
@property (nonatomic, strong) NSMutableArray *appsArray;
//存放所有下载操作的队列
@property (nonatomic, strong) NSOperationQueue *queue;
//存放所有下载操作(url是key,operation对象是value)
@property (nonatomic, strong) NSMutableDictionary *operationDict;
//缓存图片
@property (nonatomic, strong) NSMutableDictionary *imageDict; @end @implementation BWTableViewController #pragma mark - 懒加载
- (NSMutableArray *)appsArray
{
if (!_appsArray) {
NSMutableArray *appArr = [[NSMutableArray alloc] init]; NSString *path = [[NSBundle mainBundle] pathForResource:@"apps" ofType:@"plist"]; NSArray *dictArr = [NSArray arrayWithContentsOfFile:path]; for (NSDictionary *dict in dictArr) { BWApp *app = [BWApp appWithDict:dict];
[appArr addObject:app];
}
_appsArray = appArr;
}
return _appsArray;
} - (NSOperationQueue *)queue
{
if (!_queue) {
_queue = [[NSOperationQueue alloc] init];
}
return _queue;
} - (NSMutableDictionary *)operationDict
{
if (!_operationDict) {
_operationDict = [[NSMutableDictionary alloc] init];
}
return _operationDict;
} - (NSMutableDictionary *)imageDict
{
if (!_imageDict) {
_imageDict = [[NSMutableDictionary alloc] init];
}
return _imageDict;
} #pragma mark - 初始化
- (void)viewDidLoad {
[super viewDidLoad]; } - (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning]; //移除所有下载操作
[self.queue cancelAllOperations];
[self.operationDict removeAllObjects];
//移除所有图片缓存
[self.imageDict removeAllObjects];
} #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return ;
} - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.appsArray.count;
} - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellID = @"cellID"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID]; if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellID];
}
//取出模型
BWApp *app = [self.appsArray objectAtIndex:indexPath.row]; cell.textLabel.text = app.name;
cell.detailTextLabel.text = app.download; //先从imageDict缓存中取出图片url对应的image
UIImage *image = self.imageDict[app.icon]; if (image) { //说明图片已经下载成功过
cell.imageView.image = image;
}
else //说明图片未下载(没有缓存)
{
//获取caches路径,拼接文件路径
NSString *filePath = appImageCachesPath(app.icon); NSData *data = [NSData dataWithContentsOfFile:filePath]; if (data) { //沙盒中存在这个图片
cell.imageView.image = [UIImage imageWithData:data];
}
else{
//显示占位图片
cell.imageView.image = [UIImage imageNamed:@"placeholder"];
} [self download:app.icon andIndexPath:indexPath];
}
return cell;
} - (void)download:(NSString *)imageUrl andIndexPath:(NSIndexPath *)indexPath
{
//取出当前图片对应的下载操作(operation对象)
NSBlockOperation *operation = self.operationDict[imageUrl]; if (operation) return; // __weak BWTableViewController *vc = self;
__weak typeof(self) appVC = self; //创建操作,下载图片
operation = [NSBlockOperation blockOperationWithBlock:^{
NSURL *url = [NSURL URLWithString:imageUrl];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data]; //回到主线程
[[NSOperationQueue mainQueue] addOperationWithBlock:^{ //判断图片是否存在
if (image) {
//存放图片到字典中
appVC.imageDict[imageUrl] = image;
#warning 沙盒缓存
//将图片存入沙盒之中 UIImage --> NSData --> File(文件)
NSData *data = UIImagePNGRepresentation(image); // //获取caches路径
// NSString *cachesPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
//
// //拼接文件路径
// NSString *fileName = [imageUrl lastPathComponent];
// NSString *filePath = [cachesPath stringByAppendingPathComponent:fileName]; //写入缓存
[data writeToFile:appImageCachesPath(imageUrl) atomically:YES]; //UIImageJPEGRepresentation(UIImage * _Nonnull image, CGFloat compressionQuality)
}
//从字典中移除下载操作
[appVC.operationDict removeObjectForKey:imageUrl];
//刷新表格
//[self.tableView reloadData];
[appVC.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
}];
}];
//添加操作到队列中
[appVC.queue addOperation:operation];
//添加操作到字典中(为了解决重复下载)
appVC.operationDict[imageUrl] = operation;
}
//保证图片只下载过一次
//当用户开始拖拽表格时
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
//暂停下载
[self.queue setSuspended:YES];
}
//用户停止拖拽表格时
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
//恢复下载
[self.queue setSuspended:NO];
} @end

三、自定义NSOperation

 //
// BWApp.h
// IOS_0120_NSOperation防止重复下载
//
// Created by ma c on 16/1/20.
// Copyright © 2016年 博文科技. All rights reserved.
// #import <Foundation/Foundation.h> @interface BWApp : NSObject @property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *download;
@property (nonatomic, copy) NSString *icon; + (instancetype)appWithDict:(NSDictionary *)dict; @end //
// BWApp.m
// IOS_0120_NSOperation防止重复下载
//
// Created by ma c on 16/1/20.
// Copyright © 2016年 博文科技. All rights reserved.
// #import "BWApp.h" @implementation BWApp + (instancetype)appWithDict:(NSDictionary *)dict
{
BWApp *app = [[self alloc] init];
[app setValuesForKeysWithDictionary:dict];
return app;
} @end
 //
// BWDownloadOperation.h
// IOS_0120_NSOperation防止重复下载
//
// Created by ma c on 16/1/21.
// Copyright © 2016年 博文科技. All rights reserved.
// #import <Foundation/Foundation.h>
#import <UIKit/UIKit.h> @class BWDownloadOperation; @protocol BWDownloadOperationDelegate <NSObject> @optional
- (void)downloadOperation:(BWDownloadOperation *)operation didFinishDownload:(UIImage *)image; @end @interface BWDownloadOperation : NSOperation @property (nonatomic, copy) NSString *imageUrl;
@property (nonatomic, strong) NSIndexPath *indexPath; @property (nonatomic, weak) id<BWDownloadOperationDelegate> delegate; @end //
// BWDownloadOperation.m
// IOS_0120_NSOperation防止重复下载
//
// Created by ma c on 16/1/21.
// Copyright © 2016年 博文科技. All rights reserved.
// #import "BWDownloadOperation.h" @implementation BWDownloadOperation - (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:)]) {
[self.delegate downloadOperation:self didFinishDownload:image];
}
}];
}
}
@end
 //
// BWTableViewController.m
// IOS_0120_NSOperation防止重复下载
//
// Created by ma c on 16/1/20.
// Copyright © 2016年 博文科技. All rights reserved.
// #import "BWTableViewController.h"
#import "BWApp.h"
#import "BWDownloadOperation.h" #define appImageCachesPath(url) [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:[url lastPathComponent]] @interface BWTableViewController ()<BWDownloadOperationDelegate> //所有应用数据
@property (nonatomic, strong) NSMutableArray *appsArray;
//存放所有下载操作的队列
@property (nonatomic, strong) NSOperationQueue *queue;
//存放所有下载操作(url是key,operation对象是value)
@property (nonatomic, strong) NSMutableDictionary *operationDict;
//缓存图片
@property (nonatomic, strong) NSMutableDictionary *imageDict; @end @implementation BWTableViewController #pragma mark - 懒加载
- (NSMutableArray *)appsArray
{
if (!_appsArray) {
NSMutableArray *appArr = [[NSMutableArray alloc] init]; NSString *path = [[NSBundle mainBundle] pathForResource:@"apps" ofType:@"plist"]; NSArray *dictArr = [NSArray arrayWithContentsOfFile:path]; for (NSDictionary *dict in dictArr) { BWApp *app = [BWApp appWithDict:dict];
[appArr addObject:app];
}
_appsArray = appArr;
}
return _appsArray;
} - (NSOperationQueue *)queue
{
if (!_queue) {
_queue = [[NSOperationQueue alloc] init];
}
return _queue;
} - (NSMutableDictionary *)operationDict
{
if (!_operationDict) {
_operationDict = [[NSMutableDictionary alloc] init];
}
return _operationDict;
} - (NSMutableDictionary *)imageDict
{
if (!_imageDict) {
_imageDict = [[NSMutableDictionary alloc] init];
}
return _imageDict;
} #pragma mark - 初始化
- (void)viewDidLoad {
[super viewDidLoad]; } - (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning]; //移除所有下载操作
[self.queue cancelAllOperations];
[self.operationDict removeAllObjects];
//移除所有图片缓存
[self.imageDict removeAllObjects];
} #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return ;
} - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.appsArray.count;
} - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellID = @"cellID"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID]; if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellID];
}
//取出模型
BWApp *app = [self.appsArray objectAtIndex:indexPath.row]; cell.textLabel.text = app.name;
cell.detailTextLabel.text = app.download; //先从imageDict缓存中取出图片url对应的image
UIImage *image = self.imageDict[app.icon]; if (image) { //说明图片已经下载成功过
cell.imageView.image = image;
}
else //说明图片未下载(没有缓存)
{
//获取caches路径,拼接文件路径
NSString *filePath = appImageCachesPath(app.icon); NSData *data = [NSData dataWithContentsOfFile:filePath]; if (data) { //沙盒中存在这个图片
cell.imageView.image = [UIImage imageWithData:data];
}
else{
//显示占位图片
cell.imageView.image = [UIImage imageNamed:@"placeholder"];
} [self download:app.icon andIndexPath:indexPath];
}
return cell;
} - (void)download:(NSString *)imageUrl andIndexPath:(NSIndexPath *)indexPath
{
//取出当前图片对应的下载操作(operation对象)
BWDownloadOperation *operation = self.operationDict[imageUrl]; if (operation) return; //创建操作下载图片
operation = [[BWDownloadOperation alloc] init];
operation.imageUrl = imageUrl;
operation.indexPath = indexPath; //设置代理
operation.delegate = self; //添加操作到队列中
[self.queue addOperation:operation]; //添加操作到字典中(为了解决重复下载)
self.operationDict[imageUrl] = operation; } #pragma mark - 下载代理方法 - (void)downloadOperation:(BWDownloadOperation *)operation didFinishDownload:(UIImage *)image
{ //UIImageJPEGRepresentation(<#UIImage * _Nonnull image#>, <#CGFloat compressionQuality#>) //判断图片是否存在
if (image) {
//存放图片到字典中
self.imageDict[operation.imageUrl] = image; #warning 沙盒缓存
//将图片存入沙盒之中 UIImage --> NSData --> File(文件)
NSData *data = UIImagePNGRepresentation(image); //写入缓存
[data writeToFile:appImageCachesPath(operation.imageUrl) atomically:YES]; }
//从字典中移除下载操作(防止operationDict的下载操作越来越大,保证下载失败后能重新下载)
[self.operationDict removeObjectForKey:operation.imageUrl];
//刷新表格
//[self.tableView reloadData];
[self.tableView reloadRowsAtIndexPaths:@[operation.indexPath] withRowAnimation:UITableViewRowAnimationNone];
} //保证图片只下载过一次
//当用户开始拖拽表格时
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
//暂停下载
[self.queue setSuspended:YES];
}
//用户停止拖拽表格时
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
//恢复下载
[self.queue setSuspended:NO];
} @end

四、SDWebImage

 //
// BWApp.h
// IOS_0120_NSOperation防止重复下载
//
// Created by ma c on 16/1/20.
// Copyright © 2016年 博文科技. All rights reserved.
// #import <Foundation/Foundation.h> @interface BWApp : NSObject @property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *download;
@property (nonatomic, copy) NSString *icon; + (instancetype)appWithDict:(NSDictionary *)dict; @end //
// BWApp.m
// IOS_0120_NSOperation防止重复下载
//
// Created by ma c on 16/1/20.
// Copyright © 2016年 博文科技. All rights reserved.
// #import "BWApp.h" @implementation BWApp + (instancetype)appWithDict:(NSDictionary *)dict
{
BWApp *app = [[self alloc] init];
[app setValuesForKeysWithDictionary:dict];
return app;
} @end
 //
// BWTableViewController.m
// IOS_0120_NSOperation防止重复下载
//
// Created by ma c on 16/1/20.
// Copyright © 2016年 博文科技. All rights reserved.
// #import "BWTableViewController.h"
#import "BWApp.h"
#import "UIImageView+WebCache.h" @interface BWTableViewController () //所有应用数据
@property (nonatomic, strong) NSMutableArray *appsArray; @end @implementation BWTableViewController #pragma mark - 懒加载
- (NSMutableArray *)appsArray
{
if (!_appsArray) {
NSMutableArray *appArr = [[NSMutableArray alloc] init]; NSString *path = [[NSBundle mainBundle] pathForResource:@"apps" ofType:@"plist"]; NSArray *dictArr = [NSArray arrayWithContentsOfFile:path]; for (NSDictionary *dict in dictArr) { BWApp *app = [BWApp appWithDict:dict];
[appArr addObject:app];
}
_appsArray = appArr;
}
return _appsArray;
} #pragma mark - 初始化
- (void)viewDidLoad {
[super viewDidLoad]; } - (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
} #pragma mark - Table view data source //- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
//
// return 1;
//} - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { // return self.appsArray.count;
return ;
} - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *cellID = @"cellID"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID]; if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellID];
}
//取出模型
BWApp *app = [self.appsArray objectAtIndex:indexPath.row];
//设置基本信息
cell.textLabel.text = app.name;
cell.detailTextLabel.text = app.download; //下载图片
// NSURL *url = [NSURL URLWithString:@"http://img.cnblogs.com/ad/not-to-stop-questioning.jpg"]; NSURL *url = [NSURL URLWithString:app.icon];
UIImage *image = [UIImage imageNamed:@"placeholder"];
// [cell.imageView sd_setImageWithURL:url placeholderImage:image]; SDWebImageOptions options = SDWebImageRetryFailed | SDWebImageLowPriority; [cell.imageView sd_setImageWithURL:url placeholderImage:image options:options progress:^(NSInteger receivedSize, NSInteger expectedSize) { NSLog(@"下载进度:%f",(double)receivedSize / expectedSize); } completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
NSLog(@"-----图片加载完毕-----%@",image);
}]; return cell;
} @end
 - (void)applicationDidReceiveMemoryWarning:(UIApplication *)application
{
SDWebImageManager *maneger = [SDWebImageManager sharedManager];
//1.取消正在下载的操作
[maneger cancelAll];
//2.清除内存缓存
[maneger.imageCache clearMemory];
maneger.imageCache.maxCacheAge = ***;
}

IOS-多线程(NSOperation)的更多相关文章

  1. iOS 多线程 NSOperation、NSOperationQueue

    1. NSOperation.NSOperationQueue 简介 NSOperation.NSOperationQueue 是苹果提供给我们的一套多线程解决方案.实际上 NSOperation.N ...

  2. iOS多线程 NSOperation的用法

    上一篇写了 GCD 的使用,接下来就了解一下 NSOperation ,NSOperation是苹果对 GCD 的 OC 版的一个封装,但是相对于GCD来说可控性更强,并且可以加入操作依赖. NSOp ...

  3. iOS多线程--NSOperation 浅显易懂

    NSOperation是基于GCD的一套多线程实现方案,和GCD一样,线程的生命周期是由系统来自动管理的,不用像NSThread和Pthread一样让程序员手动管理.相对于GCD来说,它更加地面向对象 ...

  4. iOS多线程--NSOperation

    NSOperation是基于GCD的一套多线程实现方案,和GCD一样,线程的生命周期是由系统来自动管理的,不用像NSThread和Pthread一样让程序员手动管理.相对于GCD来说,它更加地面向对象 ...

  5. iOS多线程---NSOperation介绍和使用

    1.  NSOperation实现多线程编程,需要和NSOperationQueue一起使用. (1)先将要执行的操作封装到NSOperation中 (2)将NSOperation对象添加到NSOpe ...

  6. IOS 多线程 NSOperation GCD

    1.NSInvocationOperation NSInvocationOperation * op; NSOperationQueue * que = [[NSOperationQueuealloc ...

  7. iOS多线程---NSOperation的常用操作

    1.最大并发数: - (NSInteger)maxConcurrentOperationCount;- (void)setMaxConcurrentOperationCount:(NSInteger) ...

  8. iOS多线程编程

    废话不多说,直接上干货.先熟悉一下基本知识,然后讲一下常用的两种,NSOperation和GCD. 一.基础概念 进程: 狭义定义:进程是正在运行的程序的实例(an instance of a com ...

  9. iOS GCD NSOperation NSThread等多线程各种举例详解(拷贝)

    2年多的iOS之路匆匆而过,期间也拜读来不少大神的博客,近来突然为自己一直做伸手党感到羞耻,是时候回馈社会.回想当年自己还是小白的时候,照着一些iOS多线程教程学,也只是照抄,只知其然.不知其所以然. ...

  10. iOS 多线程学习笔记 —— NSOperation

    本文复制.参考自文章:iOS多线程编程之NSOperation和NSOperationQueue的使用 ,主要为了加强个人对知识的理解和记忆,不做他用.原作者声明: 著作权声明:本文由http://b ...

随机推荐

  1. Linux环境下proc的配置c/c++操作数据库简单示例

    在虚拟机上装了oracle11g数据库,原本想利用c/c++学习操作数据库.结果感觉摊上了一个大坑.从安装好oracle数据库到配置好proc的编译选项整整花了二天.但让我意识到自己自己几点薄弱:1. ...

  2. s3对象存储

    bkstorages 模块帮助你在蓝鲸应用中使用多种文件存储服务作为后端,用于加速静态资源,管理用户上传文件. 自定静态文件 storage 如果通过修改配置文件满足不了你的需求,你随时可以通过继承 ...

  3. Worst Performing Queries

    WITH TMP AS ( SELECT TOP 100 CAST(SUM(s.total_elapsed_time) / 1000000.0 AS DECIMAL(10, 2)) AS [Total ...

  4. ABP常见问题

    System.Data.SqlClient.SqlException (0x80131904): 'OFFSET' 附近有语法错误 解决方案:最新的ABP默认支持的是sql2012以上的版本,对于之前 ...

  5. Java之父及Java诞生

    来自为知笔记(Wiz)

  6. The adidas NMD Singapore is one of the brands top selling

    Like pointed out, we've two adidas NMD Singapore releases using the first arriving Blue and Black as ...

  7. MDI QMdiArea 多文档区域

    Qt下创建类似window平台的MDI多文档区域使用QMdiArea QMdiArea * mdiArea; mdiArea = new QMdiArea(this); //A widget 为win ...

  8. 78. Subsets(回溯)

      Given a set of distinct integers, nums, return all possible subsets (the power set). Note: The sol ...

  9. 11Qt样式表

    Qt样式表 Qt样式表的思想很大程度上是来自原HTML的层叠式样式表(CSS),通过调用Qwdiget::setStyleSheet()或是Qapplication::setStyleSheet(), ...

  10. 497. Random Point in Non-overlapping Rectangles

    1. 问题 给定一系列不重叠的矩形,在这些矩形中随机采样一个整数点. 2. 思路 (1)一个矩形的可采样点个数就相当于它的面积,可以先依次对每个矩形的面积累加存起来(相当于概率分布中的分布累积函数CD ...