在iOS中提供了4中多线程的方式
以下4中方式:
pthread使用较少
pthread
这是一套通用的多线程api,适用于linux、UNIX、windows 等系统 跨平台技术,可移植 纯c语言
NSThread *current = [NSThread currentThread];
1、创建一个线程id
pthread_t threadId;
pthrad_create(&threadId,NULL,run,NULL);
void *run(void *data)
{
return NULL;
}
NSThread
一个NSThread对象就代表一条线程
使用更加面向对象,可以直接操作线程对象,oc 语言 程序员进行管理 线程的生命周期
主线程相关用法
NSThread *current = [NSThread currentThread];
NSThread *mainThread = [NS]
判断是不是主线程
[NSThread isMainThread];
线程的优先级
NSThread threadPriority
-(BOOL)setThreadPriority:(double);
调度优先级的取值范围是0.0 — 1.0 值越大 优先级越高
1、创建线程
*1
NSThread
*thread = [[
NSThread
alloc
]
initWithTarget
:
self
selector
:
@selector
(run:)
object
:
@"aaa"
];
//
开启线程
[thread start];
*2 创建后就执行 自动启动
无法对线程进行更详细的设置
[NSThread detachNewThreadS
elector
:
@selector
(run:)
object
:
@"aaa"
];
]
3*//
隐式创建
[self
performSelectorInBackground:@selector(run:)withObject:@"aa"];
-(void)run
{
}
线程的生命周期
新建——————》线程对象进入可调度线程池(就绪状态)——————》运行状态(如果cpu调度当前线程)——————》调用sleep方法 当前线程从调度池 ,但是该线程仍然在内存中 —————》当阻塞结束 当前进程进入就绪状态
线程任务执行完毕、异常退出、强制退出 都是 线程进入死亡状态(仍然在内存中)
//阻塞线程
+(void)sleepUntiData:(NSDate:)date;
+ (void)sleepForTimeInterval:(NSTimeInterval)ti;
强制停止线程
+(void)exit; 线程进入死亡状态
线程加锁(线程同步)—》多条线程按顺序的执行任务 互斥锁 就是使用了线程同步技术
NSLock *lock = [[NSLock alloc]init];
线程读之前加锁(只能用一把锁)
@synchronized(self){ 加锁
大括号内的代码有线程安全问题代码要进行加锁操作
}大括号结束解锁
线程间通信
两个进行线程间通信的方法
下面方法在主线程中执行
settingImage
方法
[self performSelectorOnMainThread:@selector(settingImage:) withObject:image waitUntilDone:NO];
下面方法是在
onThread指定的线程中执行某个方法
[self performSelector:<#(SEL)#> onThread:<#(NSThread *)#> withObject:<#(id)#> waitUntilDone:<#(BOOL)#> modes:<#(NSArray *)#>]
对ui界面的操作要在主线程中执行,例如以下载图片为例可以使用
下面方法的意思是:在主线程中调用imageView 的 setImage:方法将imageView的image设置为 下载好的image
其中
waitUntilDone设置为NO为 调用完这个方法会立即返回
waitUntilDone设置为YES 这个方法会在主线程执行完setImage:方法后返回
[self.imageView performSelector:@selector(setImage:) onThread:[NSThread mainThread] withObject:image waitUntilDone:NO];
[
self
.
imageView
performSelectorOnMainThread
:
@selector
(setImage:)
withObject
:image
waitUntilDone
:
NO
];
GCD Grand Central Dispatch 牛逼的中枢调度器
优势:
1、多核的并行运算提出的解决方案
2、会自动利用更多的cpu内核
3、自动关了线程的生命周期(创建线程、调度任务、销毁线程)
4、不需要编写任何线程管理代码 只需要告诉GCD 要执行的任务 GCD 会自动创建队列执行任务
使用:两个步骤
定制任务
添加定制任务到队列中 —》
GCD会自动将队列中的任务取出,放到对应的线程中执行
任务的取出遵循 FIFO 先进先出
//凡是函数名种带有create\copy\new\retain等字眼,都需要在不需要使用这个数据的时候进行release
// GCD的数据类型在ARC环境下不需要再做release
// GCD的数据类型在ARC环境下不需要再做release
// CF(Core Foundation)
的数据类型在
ARC
环境下还是需要再做
release
/**
* 全局并发队列
*/
#define global_queue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 )
/**
* 主队列
*/
* 全局并发队列
*/
#define global_queue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 )
/**
* 主队列
*/
#define main_queue dispatch_get_main_queue()
基本使用:(同步函数和异步函数———决定了要不要开启新的线程)
1、2个用来执行任务的函数
同步:在当前线程中执行任务 不具备开启新线程的能力
dispatch_sync(<#dispatch_queue_t queue#>, <#^(void)block#>)
异步:在另一条线程中执行 具备了开启新线程的能力
dispatch_async(<#dispatch_queue_t queue#>, <#^(void)block#>)
特殊情况:异步函数的任务添加在主队列中(往主队列中添加一个同步任务), 任务在主线程执行,不会开启新的线程
2、队列
分为两大类(并发和串行————决定了任务的执行方式)
并发队列:可以让多个任务并发同时执行(自动开启多条线程) 在异步函数中执行
串行队列:让任务一个接着一个执行
并发队列:GCD默认已经提供了全局的并发队列供整应用程序使用,不需要手动创建
获取一个全局的默认优先级的并发队列
dispatch_queue_tqueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
添加任务到队列中执行任务
1、
用
dispatch_async
异步函数往并发队列中添加任务—————》同时开启了3个子线程
- (void)asyncGlobalQueue
{
{
// 获取一个全局的默认优先级的并发队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
// 2.添加任务到队列中执行
dispatch_async(queue, ^{
NSLog(@"----下载图片1-----%@", [NSThreadcurrentThread]);
});
dispatch_async(queue, ^{
NSLog(@"----下载图片2-----%@", [NSThreadcurrentThread]);
});
dispatch_async(queue, ^{
NSLog(@"----下载图片3-----%@", [NSThreadcurrentThread]);
// 2.添加任务到队列中执行
dispatch_async(queue, ^{
NSLog(@"----下载图片1-----%@", [NSThreadcurrentThread]);
});
dispatch_async(queue, ^{
NSLog(@"----下载图片2-----%@", [NSThreadcurrentThread]);
});
dispatch_async(queue, ^{
NSLog(@"----下载图片3-----%@", [NSThreadcurrentThread]);
});
// 总结:同时开启了3个线程
}
2、用dispatch_async异步函数 往串行队列中添加任务————————》只开了一个线程执行任务
- (void)asyncSerialQueue
{
// 1.创建串行队列
dispatch_queue_t queue = dispatch_queue_create("com.itheima.queue",NULL);
// 2.添加任务到队列中执行
dispatch_async(queue, ^{
NSLog(@"----下载图片1-----%@", [NSThreadcurrentThread]);
});
dispatch_async(queue, ^{
NSLog(@"----下载图片2-----%@", [NSThreadcurrentThread]);
});
dispatch_async(queue, ^{
NSLog(@"----下载图片3-----%@", [NSThreadcurrentThread]);
});
// 1.创建串行队列
dispatch_queue_t queue = dispatch_queue_create("com.itheima.queue",NULL);
// 2.添加任务到队列中执行
dispatch_async(queue, ^{
NSLog(@"----下载图片1-----%@", [NSThreadcurrentThread]);
});
dispatch_async(queue, ^{
NSLog(@"----下载图片2-----%@", [NSThreadcurrentThread]);
});
dispatch_async(queue, ^{
NSLog(@"----下载图片3-----%@", [NSThreadcurrentThread]);
});
//总结:只开1个线程执行任务
}
3、用dispatch_sync同步函数往并发队列中添加任务—————》不会开启新的线程,并发队列失去了并发的功能
- (void)syncGlobalQueue
{
// 1.获得全局的并发队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
// 2.添加任务到队列中执行
dispatch_sync(queue, ^{
NSLog(@"----下载图片1-----%@", [NSThreadcurrentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"----下载图片2-----%@", [NSThreadcurrentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"----下载图片3-----%@", [NSThreadcurrentThread]);
});
// 总结:不会开启新的线程,并发队列失去了并发的功能
{
// 1.获得全局的并发队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
// 2.添加任务到队列中执行
dispatch_sync(queue, ^{
NSLog(@"----下载图片1-----%@", [NSThreadcurrentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"----下载图片2-----%@", [NSThreadcurrentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"----下载图片3-----%@", [NSThreadcurrentThread]);
});
// 总结:不会开启新的线程,并发队列失去了并发的功能
}
4、
用
dispatch_sync
同步函数往串行列中添加任务—————》不会开启新的线程
- (void)syncSerialQueue
{
{
// 1.创建串行队列(串行队列)
dispatch_queue_t queue = dispatch_queue_create("com.itheima.queue",NULL);
// 2.添加任务到队列中执行
dispatch_sync(queue, ^{
NSLog(@"----下载图片1-----%@", [NSThreadcurrentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"----下载图片2-----%@", [NSThreadcurrentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"----下载图片3-----%@", [NSThreadcurrentThread]);
});
// 3.释放资源
// dispatch_release(queue); // MRC(非ARC)
// 总结:不会开启新的线程
// 2.添加任务到队列中执行
dispatch_sync(queue, ^{
NSLog(@"----下载图片1-----%@", [NSThreadcurrentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"----下载图片2-----%@", [NSThreadcurrentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"----下载图片3-----%@", [NSThreadcurrentThread]);
});
// 3.释放资源
// dispatch_release(queue); // MRC(非ARC)
// 总结:不会开启新的线程
}
5、
用
dispatch_sync
同步函数
,
在主线程中往主队列中添加任务
:
任务无法往下执行———————>产生死锁(死循环)
- (void)syncMainQueue
{
// 1.获得主队列
dispatch_queue_t queue = dispatch_get_main_queue();
{
// 1.获得主队列
dispatch_queue_t queue = dispatch_get_main_queue();
// 2.添加任务到队列中执行
(queue, ^{
NSLog(@"----下载图片1-----%@", [NSThreadcurrentThread]);
});
// dispatch_sync(queue, ^{
// NSLog(@"----下载图片2-----%@", [NSThread currentThread]);
// });
// dispatch_sync(queue, ^{
// NSLog(@"----下载图片3-----%@", [NSThread currentThread]);
// });
});
// dispatch_sync(queue, ^{
// NSLog(@"----下载图片2-----%@", [NSThread currentThread]);
// });
// dispatch_sync(queue, ^{
// NSLog(@"----下载图片3-----%@", [NSThread currentThread]);
// });
}
6、 使用dispatch_async异步函数,在主线程中往主队列中添加任务
特殊情况:异步函数的任务添加在主队列中(往主队列中添加一个同步任务), 任务在主线程执行,不会开启新的线程
- (
void
)asyncMainQueue
{
// 1.获得主队列(串行队列)
dispatch_queue_t
queue =
dispatch_get_main_queue
();
// 2. 添加任务到队列中 执行
dispatch_async (queue, ^{
NSLog ( @"---- 下载图片 1-----%@" , [ NSThread currentThread ]);
});
// 2. 添加任务到队列中 执行
dispatch_async (queue, ^{
NSLog ( @"---- 下载图片 1-----%@" , [ NSThread currentThread ]);
});
}
同步函数(sync)
并发队列:不会开启线程
串行队列:不会开启线程
异步函数(async)
并发队列:开启多个线程
串行队列:开启一条线程
使用GCD进行异步图片下载
1、获取全局并发队列
dispatch_queue_tqueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
2、调用异步(同步)函数下载图片
dispatch_async(queue, ^{//开启异步线程下载图片
NSLog(@"当前线程%@",[NSThreadcurrentThread]);
NSURL *url = [NSURLURLWithString:@"http://www.res.meizu.com/resources/www_image/weixin.jpg"];
NSData *data = [NSDatadataWithContentsOfURL:url];
UIImage *image = [UIImageimageWithData:data];
NSURL *url = [NSURLURLWithString:@"http://www.res.meizu.com/resources/www_image/weixin.jpg"];
NSData *data = [NSDatadataWithContentsOfURL:url];
UIImage *image = [UIImageimageWithData:data];
3、回到主队列刷新图片
dispatch_async(dispatch_get_main_queue(), ^{
self.imageView.image= image;
});
self.imageView.image= image;
});
});
GCD的其他用法
GCD的其他用法
1、延迟执行
*1 [self performSelector:@selector(run) withObject:nil afterDelay:2.0];
*2 利用GCD 进行延迟执行(推荐)
dispatch_queue_t queue =
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// /**
// * 2 秒钟后 在队列 queue 中执行 block 中的任务
// */
// dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), queue, ^{
//
// * 2 秒钟后 在队列 queue 中执行 block 中的任务
// */
// dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), queue, ^{
//
// });
2、一次性代码 使某一段代码在整个程序运行过程中只执行一次,用于创建单
dispatch_once
static id _instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [[self alloc]init];
});
3、队列组 当程序需要执行完多个耗时操作后 在执行某个其他操作的时候使用
如:下载两张图片 下载完成后进行拼接显示在imageView上
*1、 创建一个组
dispatch_group_t group = dispatch_group_create();
*2、开启一个任务下载图片1
__block UIImage *image1 = nil;
//开启一个任务下载图片1
dispatch_group_async(group, global_queue, ^{
image1 = [self imageWithUrl:@"1"];
//开启一个任务下载图片1
dispatch_group_async(group, global_queue, ^{
image1 = [self imageWithUrl:@"1"];
});
*3 开启一个任务下载图片2
__block UIImage *image2 = nil;
//开启一个任务下载图片2
//开启一个任务下载图片2
dispatch_group_async(group, global_queue, ^{
image2 = [self imageWithUrl:@"2"];
});
4* 等待group中的所有任务都执行完毕后 在执行其他操作
dispatch_group_notify(group, main_queue, ^{
//
合并图
UIGraphicsBeginImageContextWithOptions(CGSizeMake(200, 100), NO, 0.0);
[image1 drawInRect:CGRectMake(0, 0, 100, 100)];
[image2 drawInRect:CGRectMake(100, 0, 100, 100)];
UIImageView *imageView = nil;
imageView.image = UIGraphicsGetImageFromCurrentImageContext();
});
NSOperation
使用NSOperation 的子类 创建任务
NSInvocationOperation 、 NSBlockOperation
1、封装任务
NSInvocationOperation *opration1 = [[NSInvocationOperationalloc]initWithTarget:selfselector:@selector(download)object:nil];
NSInvocationOperation *opration2 = [[NSInvocationOperationalloc]initWithTarget:selfselector:@selector(run)object:nil];
NSBlockOperation
*blockOperation = [
NSBlockOperation
blockOperationWithBlock
:^{
NSLog ( @"%@——1----" ,[ NSThread currentThread ]);
NSLog ( @"%@——1----" ,[ NSThread currentThread ]);
}];
[
blockOperation
addExecutionBlock:^{
NSLog ( @"%@—2-------" ,[ NSThread currentThread ]);
NSLog ( @"%@—2-------" ,[ NSThread currentThread ]);
}];
以上有三个操作(
opration1、
opration2、
blockOperation
) 4个任务(
download、
run、
%@——1——、
%@——2----
)
2、创建队列
NSOperationQueue*queue = [[NSOperationQueuealloc]init];
//
最大并发数
同一时间只能做
2
件事
控制开线程的个数
queue.maxConcurrentOperationCount= 2;//2---3
//
任务在队列中的优先级
/*
NSOperationQueuePriorityVeryLow = -8L,
NSOperationQueuePriorityLow = -4L,
NSOperationQueuePriorityNormal = 0,
NSOperationQueuePriorityHigh = 4,
NSOperationQueuePriorityVeryHigh = 8
NSOperationQueuePriorityVeryLow = -8L,
NSOperationQueuePriorityLow = -4L,
NSOperationQueuePriorityNormal = 0,
NSOperationQueuePriorityHigh = 4,
NSOperationQueuePriorityVeryHigh = 8
*/
opration1.queuePriority= NSOperationQueuePriorityNormal;
操作依赖
//
操作依赖
在添加到队列之前
----
可以再不同队列间的
operation
之间添加依赖
不能相互依赖
//opration1依赖 opration2 当opration2执行完毕后才能 执行opration1
[opration1addDependency:opration2];
//
操作的监听
// 当 blockOperation 中的操作完成后 在当前线程中执行下面操作
blockOperation. completionBlock= ^{
// 当 blockOperation 中的操作完成后 在当前线程中执行下面操作
blockOperation. completionBlock= ^{
};
//添加到队列中---------》异步执行 多个任务一定是并行操作[queueaddOperation:opration1];
[queueaddOperation:opration2];
[queueaddOperation:blockOperation];
自定义NSOperation
创建属性
/**
* 下载图片的队列
*/
@property(nonatomic,strong)NSOperationQueue *queue;
/** key:url value:operation对象*/
* 下载图片的队列
*/
@property(nonatomic,strong)NSOperationQueue *queue;
/** key:url value:operation对象*/
@property(nonatomic,strong)NSMutableDictionary *operations;
/** key:url value:image对象*/
@property(nonatomic,strong)NSMutableDictionary *images;
懒加载
- (NSArray*)apps
{
if (!_apps) {
NSArray *dictArray = [NSArrayarrayWithContentsOfFile:[[NSBundlemainBundle]pathForResource:@"apps.plist"ofType:nil]];
NSMutableArray *appArray = [NSMutableArrayarray];
for (NSDictionary*dict in dictArray) {
HMApp *app = [HMAppappWithDict:dict];
[appArray addObject:app];
}
_apps = appArray;
}
return _apps;
}
- (NSOperationQueue*)queue
{
if (!_queue) {
_queue = [[NSOperationQueuealloc]init];
_queue.maxConcurrentOperationCount= 3;// 最大并发数 == 3
}
return _queue;
}
- (NSMutableDictionary*)operations
{
if (!_operations) {
_operations = [NSMutableDictionarydictionary];
}
return _operations;
}
- (NSMutableDictionary*)images
{
if (!_images) {
_images = [NSMutableDictionarydictionary];
}
return _images;
{
if (!_apps) {
NSArray *dictArray = [NSArrayarrayWithContentsOfFile:[[NSBundlemainBundle]pathForResource:@"apps.plist"ofType:nil]];
NSMutableArray *appArray = [NSMutableArrayarray];
for (NSDictionary*dict in dictArray) {
HMApp *app = [HMAppappWithDict:dict];
[appArray addObject:app];
}
_apps = appArray;
}
return _apps;
}
- (NSOperationQueue*)queue
{
if (!_queue) {
_queue = [[NSOperationQueuealloc]init];
_queue.maxConcurrentOperationCount= 3;// 最大并发数 == 3
}
return _queue;
}
- (NSMutableDictionary*)operations
{
if (!_operations) {
_operations = [NSMutableDictionarydictionary];
}
return _operations;
}
- (NSMutableDictionary*)images
{
if (!_images) {
_images = [NSMutableDictionarydictionary];
}
return _images;
}
cell中下载图片的代码
//显示图片
// 保证一个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 = [[HMDownloadOperationalloc]init];
operation.url= app.icon;
operation.delegate= self;
operation.indexPath= indexPath;
[self.queueaddOperation:operation];// 异步下载
self.operations[app.icon] = operation;
}
// 保证一个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 = [[HMDownloadOperationalloc]init];
operation.url= app.icon;
operation.delegate= self;
operation.indexPath= indexPath;
[self.queueaddOperation:operation];// 异步下载
self.operations[app.icon] = operation;
}
}
#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 )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)#>];
}
}
tableView滚动的时候的操作
- (void)scrollViewWillBeginDragging:(UIScrollView*)scrollView
{
// 开始拖拽
// 暂停队列
[self.queuesetSuspended:YES];
}
- (void)scrollViewWillEndDragging:(UIScrollView*)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inoutCGPoint *)targetContentOffset
{
[self.queuesetSuspended:NO];
{
// 开始拖拽
// 暂停队列
[self.queuesetSuspended:YES];
}
- (void)scrollViewWillEndDragging:(UIScrollView*)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inoutCGPoint *)targetContentOffset
{
[self.queuesetSuspended:NO];
}
自定义NSOperation的代码
HMDownloadOperation.h
@classHMDownloadOperation;
@protocolHMDownloadOperationDelegate <NSObject>
@optional
- (void)downloadOperation:(HMDownloadOperation*)operation didFinishDownload:(UIImage*)image;
@end
@interfaceHMDownloadOperation : NSOperation
@property(nonatomic,copy)NSString *url;
@property(nonatomic,strong)NSIndexPath *indexPath;
@property(nonatomic,weak)id<HMDownloadOperationDelegate> delegate;
@protocolHMDownloadOperationDelegate <NSObject>
@optional
- (void)downloadOperation:(HMDownloadOperation*)operation didFinishDownload:(UIImage*)image;
@end
@interfaceHMDownloadOperation : NSOperation
@property(nonatomic,copy)NSString *url;
@property(nonatomic,strong)NSIndexPath *indexPath;
@property(nonatomic,weak)id<HMDownloadOperationDelegate> delegate;
@end
HMDownloadOperation.m
/**
* 在main方法中实现具体操作
*/
- (void)main
{
@autoreleasepool {
if (self.isCancelled)return;
NSURL *downloadUrl = [NSURLURLWithString:self.url];
NSData *data = [NSDatadataWithContentsOfURL:downloadUrl];// 这行会比较耗时
if (self.isCancelled)return;
UIImage *image = [UIImageimageWithData:data];
if (self.isCancelled)return;
if ([self.delegaterespondsToSelector:@selector(downloadOperation:didFinishDownload:)]) {
dispatch_async(dispatch_get_main_queue(), ^{ // 回到主线程,传递图片数据给代理对象
[self.delegatedownloadOperation:selfdidFinishDownload:image];
});
}
}
* 在main方法中实现具体操作
*/
- (void)main
{
@autoreleasepool {
if (self.isCancelled)return;
NSURL *downloadUrl = [NSURLURLWithString:self.url];
NSData *data = [NSDatadataWithContentsOfURL:downloadUrl];// 这行会比较耗时
if (self.isCancelled)return;
UIImage *image = [UIImageimageWithData:data];
if (self.isCancelled)return;
if ([self.delegaterespondsToSelector:@selector(downloadOperation:didFinishDownload:)]) {
dispatch_async(dispatch_get_main_queue(), ^{ // 回到主线程,传递图片数据给代理对象
[self.delegatedownloadOperation:selfdidFinishDownload:image];
});
}
}