iOS开发多线程篇—基础知识 NSOperation

iOS开发多线程篇:NSOperation原理与实践
本文详细介绍了iOS开发中NSOperation的基本概念、使用方式、子类及队列管理,包括创建、执行、优先级、依赖、执行顺序等关键点,以及自定义NSOperation的步骤。通过实例代码演示了如何使用NSOperation实现异步任务执行。

-------NSOperation简介----

1.NSOperation的作用

·配合使用NSOperation和NSOperationQueue也能实现多线程编程

2.NSOperation和NSOperationQueue实现多线程的具体步骤

·先将需要执行的操作封装到一个NSOperation对象中

·然后将NSOperation对象添加到NSOperationQueue中

·系统会自动将NSOperation中封装的操作放到一条新线程中执行

---------NSOperation的子类----

3.NSOperation是个抽象类,并不具备封装操作的能力,必须使用它的子类

4.使用NSOperation子类的方式有3种

·NSInvocationOperation

·NSBlockOperation

·自定义子类继承NSOperation,实现内部相应的方法

------NSInvocationOperation---

5.创建NSInvocationOperation对象

- (id)initWithTarget:(id)target selector:(SEL)sel object:(id)arg;

6.调用start方法开始执行操作

- (void)start;

一旦执行操作,就会调用target的sel方法

7.注意

·默认情况下,调用了start方法后并不会开一条新线程去执行操作,而是在当前线程同步执行操作

·只有将NSOperation放到一个NSOperationQueue中,才会异步执行操作

-------NSBlockOperation--

8.创建NSBlockOperation对象

+ (id)blockOperationWithBlock:(void (^)(void))block;

9.通过addExecutionBlock:方法添加更多的操作

- (void)addExecutionBlock:(void (^)(void))block;

注意:只要NSBlockOperation封装的操作数 > 1,就会异步执行操作

-------NSOperationQueue----

10.NSOperationQueue的作用

·NSOperation可以调用start方法来执行任务,但默认是同步执行的

·如果将NSOperation添加到NSOperationQueue(操作队列)中,系统会自动异步执行NSOperation中的操作

11.添加操作到NSOperationQueue中

- (void)addOperation:(NSOperation *)op;

- (void)addOperationWithBlock:(void (^)(void))block;

-------最大并发数----

12.什么是并发数

·同时执行的任务数

·比如,同时开3个线程执行3个任务,并发数就是3

13.最大并发数的相关方法

- (NSInteger)maxConcurrentOperationCount;

- (void)setMaxConcurrentOperationCount:(NSInteger)cnt;

-----队列的取消、暂停、恢复------

14.取消队列的所有操作

- (void)cancelAllOperations;

提示:也可以调用NSOperation的- (void)cancel方法取消单个操作

15.暂停和恢复队列

- (void)setSuspended:(BOOL)b; // YES代表暂停队列,NO代表恢复队列

- (BOOL)isSuspended;

----操作优先级-----

16.设置NSOperation在queue中的优先级,可以改变操作的执行顺序

- (NSOperationQueuePriority)queuePriority;

- (void)setQueuePriority:(NSOperationQueuePriority)p;

17.优先级的取值(优先级越高,越先执行)

·NSOperationQueuePriorityVeryLow = -8L,

·NSOperationQueuePriorityLow = -4L,

·NSOperationQueuePriorityNormal = 0,

·NSOperationQueuePriorityHigh = 4,

·NSOperationQueuePriorityVeryHigh = 8

---操作依赖---

18.NSOperation之间可以设置依赖来保证执行顺序

·比如一定要让操作A执行完后,才能执行操作B,可以这么写

[operationB addDependency:operationA]; // 操作B依赖于操作A

19.可以在不同queue的NSOperation之间创建依赖关系

20. 注意:不能相互依赖

·比如A依赖B,B依赖A

----操作的执行顺序---

21.对于添加到queue中的operations,它们的执行顺序取决于2点

·首先依据NSOperation之间的依赖关系

·然后依据NSOperation的优先级

22.因此,总体的执行顺序是

·先满足依赖关系

·然后再从NSOperation中选择优先级最高的那个执行

---自定义NSOperation---

23.自定义NSOperation的步骤很简单

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

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

·自己创建自动释放池(因为如果是异步操作,无法访问主线程的自动释放池)

·经常通过- (BOOL)isCancelled方法检测操作是否被取消,对取消做出响应

--------分割线---

NSOperation小代码1,

只写一个文件参考下

//  DYFViewController.m
//  624-03-NSOperation
//
//  Created by dyf on 14-6-24.
//  Copyright (c) 2014年 ___FULLUSERNAME___. All rights reserved.
// #import "DYFViewController.h" @interface DYFViewController () @end @implementation DYFViewController - (void)viewDidLoad {  [super viewDidLoad];  // Do any additional setup after loading the view, typically from a nib.   [self testOperationQueue]; } - (void)testOperationListen {  NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{   NSLog(@"下载图片1111111%@", [NSThread currentThread]);   // 下载图片  }];  operation3.completionBlock = ^{   // 下载完图片后想做的时期  };  // 2.创建队列  NSOperationQueue *queue = [[NSOperationQueue alloc] init];  [queue addOperation:operation3]; } - (void)testOperationQueue {  // 1.封装操作  NSInvocationOperation *operation1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download) object:nil];  NSInvocationOperation *operation2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil];   NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{   NSLog(@"1111111%@", [NSThread currentThread]);  }];   [operation3 addExecutionBlock:^{   NSLog(@"222222%@", [NSThread currentThread]);  }];  [operation3 addExecutionBlock:^{   NSLog(@"33333%@", [NSThread currentThread]);  }];  // 2.创建队列  NSOperationQueue *queue = [[NSOperationQueue alloc] init];  // 5以内,2~3为宜  queue.maxConcurrentOperationCount = 2; #warning 面试题  // 设置操作依赖(一定要在添加到队列中前设置)  [operation2 addDependency:operation1]; // 执行顺序取决于依赖,先执行完operation1再执行operation2 // 注意:不能相互依赖,循环操作   // 3.添加操作到队列中(自动执行操作,自动开启线程)  [queue addOperation:operation1];  [queue addOperation:operation2];  [queue addOperation:operation3];   // 取消所有线程  //[queue cancelAllOperations];   // 暂停队列  //[queue setSuspended:YES];   // 设置操作优先级  //operation1.queuePriority = NSOperationQueuePriorityVeryHigh;   } - (void)testNSBlockOperation {  // 1.创建操作对象,封装要执行的任务  NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{   for (int i = 0; i < 11; i++) {    NSLog(@"1111111%@", [NSThread currentThread]);   }  }];  // 任务数在2各以上,就会开线程  [operation addExecutionBlock:^{   for (int i = 0; i < 11; i++) {    NSLog(@"222222%@", [NSThread currentThread]);   }  }];  [operation addExecutionBlock:^{   for (int i = 0; i < 11; i++) {    NSLog(@"33333%@", [NSThread currentThread]);   }  }];  // 2.执行操作  [operation start]; } - (void)testNSInvocationOperation {  // 1.创建操作对象,封装要执行的任务  NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download) object:nil];  // 2.执行操作(默认情况下,若操作没有放到队列queue中,都是同步执行)  [operation start]; } - (void)download {  for (int i = 0; i < 11; i++) {   NSLog(@"download-----%@", [NSThread currentThread]);  } } - (void)run {  for (int i = 0; i < 11; i++) {   NSLog(@"run------%@", [NSThread currentThread]);  } } @end

----自定义NSOperation---

//
//  DYFDownloadOperation.h
//  624-05-自定义Operation
//
//  Created by dyf on 14-6-24.
// Copyright (c) 2014年 dyf. All rights reserved. // #import <Foundation/Foundation.h> @class DYFDownloadOperation; @protocol DYFDownloadOperationDelegate <NSObject> @optional - (void)downloadOperation:(DYFDownloadOperation *)operation didFinishedDownload:(UIImage *)image; @end @interface DYFDownloadOperation : NSOperation @property (nonatomic, copy) NSString *url; @property (nonatomic, strong) NSIndexPath *indexPath; @property (nonatomic, weak) id<DYFDownloadOperationDelegate> delegate; @end
//
//  DYFDownloadOperation.m
//  624-05-自定义Operation
//
//  Created by dyf on 14-6-24.
// Copyright (c) 2014年 dyf. All rights reserved. // #import "DYFDownloadOperation.h" @implementation DYFDownloadOperation /** * 在main方法中实现具体操作 */ - (void)main {  @autoreleasepool {   if (self.isCancelled) return;   NSURL *imaUrl = [NSURL URLWithString:self.url];   if (self.isCancelled) return;   // 下面这行很耗时   NSData *data = [NSData dataWithContentsOfURL:imaUrl];   if (self.isCancelled) return;   UIImage *image = [UIImage imageWithData:data];   if (self.isCancelled) return;     // 返回主线程显示图片   // 通过代理   if ([self.delegate respondsToSelector:@selector(downloadOperation:didFinishedDownload:)]) {    [self.delegate downloadOperation:self didFinishedDownload:image];   }  } } @end

具体利用MVC模式创建的文件老生常谈,只来一个Controller.m文件供参考,数据存储存在问题,可以改用SDWebImage框架处理

//
//  DYFTableViewController.m
//  624-05-自定义Operation
//
//  Created by dyf on 14-6-24.
// Copyright (c) 2014年 ___FULLUSERNAME___. All rights reserved. // #import "DYFTableViewController.h" #import "DYFAppModel.h" #import "DYFDownloadOperation.h" #warning Dictionary基础知识不太理解,字典的赋值回去看看笔记 @interface DYFTableViewController ()<DYFDownloadOperationDelegate> @property (nonatomic, strong) NSArray *apps; @property (nonatomic, strong) NSOperationQueue *queue; /** * key:url value:operation对象 */ @property (nonatomic, strong) NSMutableDictionary *oprations; /** * key:url value:image对象 */ @property (nonatomic, strong) NSMutableDictionary *images; @end @implementation DYFTableViewController #pragma mark - 4个懒加载 - (NSArray *)apps {  if (!_apps) {   NSString *path = [[NSBundle mainBundle] pathForResource:@"apps" ofType:@"plist"];   NSArray *arrayApps = [NSArray arrayWithContentsOfFile:path];     NSMutableArray *arrayM = [NSMutableArray arrayWithCapacity:arrayApps.count];   for (NSDictionary *dict in arrayApps) {    DYFAppModel *appM = [DYFAppModel appWithDict:dict];    [arrayM addObject:appM];   }   _apps = arrayM;  }  return _apps; } - (NSOperationQueue *)queue {  if (!_queue) {   _queue = [[NSOperationQueue alloc] init];   // 设置最大并发线程数,最多同时下载3张图片   _queue.maxConcurrentOperationCount = 3;  }  return _queue; } - (NSMutableDictionary *)oprations {  if (!_oprations) {   _oprations = [[NSMutableDictionary alloc] init];  }  return _oprations; } - (NSMutableDictionary *)images {  if (!_images) {   _images = [NSMutableDictionary dictionary];  }  return _images; } - (void)viewDidLoad {  [super viewDidLoad];  // Do any additional setup after loading the view, typically from a nib. } #pragma mark - 数据源方法 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {  return self.apps.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {  // 1.创建cell  static NSString *identifier = @"apps";  UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];  if (!cell) {   cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier];  }  // 2.设置cell的数据  DYFAppModel *app = self.apps[indexPath.row];  cell.textLabel.text = app.name;  cell.detailTextLabel.text = app.download;   // 重点是如何从网络下载图片传入cell上面  // 每个url对应一个DYFDownloadOperation对象  // 每个url对应一个image对象  UIImage *image = self.images[app.icon];  if (image) {   // 若缓存中存在图片   cell.imageView.image = image;  }else  {   // 若缓存中不存在图片,则图片要从网上下载   // 设置下载前系统刷出的图片   cell.imageView.image = [UIImage imageNamed:@"身份证小"];     // 基础差,下面这行不太理解   DYFDownloadOperation *operation = self.oprations[app.icon];   if (operation) {    // 若正在下载,则不执行其它操作   }else   {    // 若没在下载,则创建开始下载的子线程    DYFDownloadOperation *operation = [[DYFDownloadOperation alloc] init];    operation.url = app.icon;    operation.indexPath = indexPath;    operation.delegate = self;    // 添加任务进队列,异步下载    [self.queue addOperation:operation];    // 基础差,下面这行不太理解    self.oprations[app.icon] = operation;   }  }   // 3.返回cell  return cell; } #pragma mark - DYFDownloadOperationDelegate - (void)downloadOperation:(DYFDownloadOperation *)operation didFinishedDownload:(UIImage *)image {  // 1.删除执行完毕的下载操作  [self.oprations removeObjectForKey:operation.url];  // 若图片下载好  if (image) {   // 2.将下载好的图片存入缓存   self.images[operation.url] = image;   // 3.刷新这一行cell的数据   [self.tableView reloadRowsAtIndexPaths:@[operation.indexPath] withRowAnimation:UITableViewRowAnimationNone];   // 4.将图片存入沙盒     // 4.1图片先转换为2进制数据   NSData *data = UIImagePNGRepresentation(image);   // 4.2设置沙盒路径   NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:[self.apps[operation.indexPath.row] icon]];   NSLog(@"%@", path);   // 4.3保存data到path中   [data writeToFile:path atomically:YES];  } } // 开始拖拽时候暂停队列 - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {  [self.queue setSuspended:YES]; } // 停止拖拽的时候重启队列 - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset {  [self.queue setSuspended:NO]; } @end
 
 
绿色通道:  好文要顶  关注我  收藏该文 与我联系 
0
0
 
(请您对文章做出评价)
 
« 上一篇: iOS开发多线程篇—NSOperation基本操作 - 文顶顶
» 下一篇: iOS开发网络篇—网络编程基础

posted on 2015-05-03 19:59 iosblog's 阅读(6) 评论(0) 编辑 收藏

 
posted on 2015-05-13 15:52 城之内 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/HypeCheng/p/4500678.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值