IOS中级篇—— 多线程--NSOperation

NSOperation 操作? 任务是对代码的封装, 操作是对任务的封装 --目的:就是可以随时的暂停/恢复/取消任务;

NSOperation 对GCD的封装. OC 运用起来更加方便. 抽象类. 车

NSOperation的使用:

<1> 操作直接调用 start方法,就是在当前线程执行(Block中封装的任务数大于1的情况除外).

<2> 就是将操作放在队列中.自动的帮我们开启线程,来执行操作.

两个子类:

NSInvocationOperation: 调用

? ? ?

1. NSOperation的两个子类的使用:

?// 创建一个NSOpertation的子类 NSInvocationOperation

? ?? NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self ? ?? ?????selector:@selector(longTimeOperation) object:nil];

? ? ?[op1 start]; ?//调用 ?开始任务 ?

? ? ? 不会开启线程。 ?在主线程中执行?

?NSBlockOperation:Block

? // 创建一个NSOpertation的子类 ?NSBlockOperation

??? NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
??????? // Block中封装操作.
??????? [self longTimeOperation];

??? }];

//?追加一个操作(任务).

??? [op2 addExecutionBlock:^{

??????? NSLog(@"下载图片1:%@",[NSThread currentThread]);

??? }];

? // 追加一个操作(任务).

??? [op2 addExecutionBlock:^{

??????? NSLog(@"下载图片2:%@",[NSThread currentThread]);

??? }];

// [op2 start];

?? // NSBlockOperation 直接调用start方法:

?? // 如果只有一个任务:在主线程中执行

?? // 如果有多个任务:会开启多条线程,在主线程中和子线程中都执行任务.

?? // 多个任务都是同时执行的.

??? // 操作完成之后的回调(异步的回调)
??? // 一般用的不多.
??? op2.completionBlock = ^{
??????? // 操作执行完毕的回调(什么时候操作执行完毕,我们并不知道)
??????? NSLog(@"操作1执行完毕%@",[NSThreadcurrentThread]);

??? };

? ?

?// 创建一个非队列: ?非主队列:非主队列存放的操作都在子主线程中执行.

??? NSOperationQueue *queue = [[NSOperationQueue alloc] init];

?// 获取一个主队列 ??主队列:主队列存放的操作在主线程中执行

??? NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];

?// 使用:将操作添加到队列中

??? [queue? ?addOperation:op2];

??? [queue?addOperation:op1];

?// 将操作添加到队列中,会自动(开启线程)的异步执行操作.

? ? 任务增加到队列中。 就调用Operation里的main方法。 ?然后自动执行任务? ? ?

任务依赖

? ? [op1 addDependency:op2]; ?//等任务 op2 执行完后 在执行op1

??? [op2 addDependency:op3]; ?//等任务 op3 执行完后 在执行op2

? ? ?这两句的效果是: op3最先执行 在op2 执行 ?最后执行 op1

高级操作:

一般情况下 队列都用懒加载的方法来实现

@property (nonatomic, strong) NSOperationQueue *queue;

? ? ? // 懒加载Queue
-(NSOperationQueue *)queue
{
??? if (!_queue) {
??????? _queue = [[NSOperationQueuealloc] init];
??????? // 最大并发数为6 .
??????? [_queuesetMaxConcurrentOperationCount:6];
??? }
??? return_queue;

}

在block中 用到self 都要用weak方式 ? 否则会造循环引用问题

_weaktypeof(self) wself = self;?

NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{

??????[wself longTimeOperation];

}];

? ? // 取消单个操作,一般也不用.

??? [op2 cancel];

??? // 暂停队列中的操作

??? [self.queue setSuspended:YES];

??? // 恢复队列中的操作

??? [self.queue setSuspended:NO];

??? // 取消所有操作,对于已经取消的操作,就永远取消了,不会再次开启

??? [self.queue cancelAllOperations];

// 自定义NSOperation; 线程间通讯

??? NSBlockOperation *op = [NSBlockOperationblockOperationWithBlock:^{
??????? // 执行的任务
??????????? UIImage *image = [selflongTimeOperation];
??????????? NSBlockOperation *op = [NSBlockOperationblockOperationWithBlock:^{

? ? ? ? ? ? ? self.imageView.image = image;

? ? ? ? ?? }];

? ? ? ? [[NSOperationQueue mainQueue] addOperation:op];

??? }];

下面都是自定义NSOperation方式

// 不同对象间的通讯

三种方式

? ? ? ?? 1.通知

1.>// 下载图片完成的时候?发送一个通知,将图片传递出去(通知中的参数是image) ?

[[NSNotificationCenter defaultCenter] postNotificationName:@"ITDownloadImageOperation" object:image];

2.>// 在需要用到内容的类 注册通知的接收者.

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(setUpImage:)?name:@"ITDownloadImageOperation" object:nil];

3.>// 通知传递的参数,永远是一个NSNotification; ? 注册通知时用到的方法

- (void)setUpImage:(NSNotification *)notify

{

??? // 回到主线程

??? dispatch_async(dispatch_get_main_queue(), ^{?

??????? NSLog(@"setUpImage%@",[NSThread currentThread]);

??????? // notify.object就是通知传递的对象.

??????? // 本次通知中,通知传递的对象就是这个操作

??????? ITDownloadImageOperation *op = notify.object;

??????? self.imageView.image = op.image;

??? });

}

? ? ?? 2.代理

? ? ? ? ? ? ? ?? ?参考以前代理的写法 ? 一模一样

? ? ?? 3.block

// 1.定义一个block类型 ?参数为image

typedefvoid (^downloadImageOperationBlock)(UIImage *image);

// 2.定义一个Block的属性

@property (nonatomic, copy) downloadImageOperationBlock downBlock;

// 3. 设置Block中想要执行的内容;

// Block 只是一个块代码.Block中的内容什么时候执行,和定义其中的内容是分开进行的.

op.downBlock = ^(UIImage *image){

? ? // Block中想要执行的内容.

? ? self.imageView.image = image;

};

// 4. 在 main执行这个Block ?

-(void)main

{

??? @autoreleasepool {

// 在子线程下载图片

??????? UIImage *image = [self downloadImage];

?// 回到主线程

??????? [[NSOperationQueue mainQueue] addOperationWithBlock:^{

if (self.downBlock) {

? ? ? self.downBlock(image);

? ? ? NSLog(@"执行Block中的内容: 设置图片");

}

}];

}

}

3.block 方法形式 传单个对象 如UIImage

前两步 跟上面一样

// 3.定义一个方法,负责传递Block

// (downloadImageOperationBlock)blk:把Block当做一个参数来传递

- (void)setUpImageWithBlock:(downloadImageOperationBlock)blk;

// 4.实现这个方法,self.downBlock赋值

-(void)setUpImageWithBlock:(downloadImageOperationBlock)blk

{

??? if (blk) {

??????? // 给self.downBlock赋值(Block内部执行的方法)

??????? self.downBlock = blk;

??? }

}

? ? // 5.Block中的内容是一个参数

??? [op setUpImageWithBlock:^(UIImage *image) {

??????? // 定义一个Block中执行的内容.

??????? self.imageView.image = image;

??? }];

? ? ?????// 6.调用block ?与上面第4步一样

?? 3.block 方法形式 传本身类 ? ?

? ? ? ? ? ? ? ?? ? ?些方法跟 传单个对象用法一模一样 只是在调用bolck时传self

? ? ? ? ? ? ? ? ? ??self.downBlock(image);

? ? ?? ? 在设置值的时候 用对象.某个对象

? ITDownloadOperationBlock *op = [[ITDownloadOperationBlockalloc] init];

? [op setUpImageWithBlock:^(ITDownloadOperationBlock *op) {

? ? ? self.imageView.image = op.image;

? }];? ? ?

? ?

?

时间: 2024-12-15 13:43:35

IOS中级篇—— 多线程--NSOperation的相关文章

IOS中级篇 —— 多线程 - GCD

GCD 是c语言的框架,不需要手动管理内存 是一个面向任务   不是面向线程,不需要管理线程的生命周期 GCD 任务/队列 执行函数 任务:Block  任务都封闭在Block中.  —— 线程执行 队列:存放任务    FIFO (先进先出的原则) GCD中的队列: 串行队列:想要任务按顺序执行 //    创建一个串行队列 dispatch_queue_t serialQueue = dispatch_queue_create("serial", DISPATCH_QUEUE_SE

iOS中的多线程 NSOperation

在ios中,使用多线程有三种方式,分别是:NSThread.NSOperation和NSOperationQueue.GCD,在本节,主要讲解一下NSOperation的使用. NSOperation和NSOperationQueue这种方式实际上是将NSOperation的对象放到一个NSOperationQueue队列中,然后依次启动操作,类似于线程池的使用. 在使用的过程中,NSOperation的操作使用的是它的子类,分别是NSInvocationOperation和NSBlockOpe

IOS——中级篇 --TableView以及Cell

????? //? 设置tableView的行高 ??? self.tableView.rowHeight = 100;//? 设置tableView分割线的样式//? UITableViewCellSeparatorStyleNone 不显示分割线//? UITableViewCellSeparatorStyleSingleLine? 显示分割线(默认) ??? self.tableView.separatorStyle = UITableViewCellSeparatorStyleSingl

IOS中级篇 —— 日期时间对象

结合NSCalendar和NSDate能做更多的日期\时间处理 获得NSCalendar对象 NSCalendar *calendar = [NSCalendar currentCalendar];?获得年月日 - (NSDateComponents *)components:(NSCalendarUnit)unitFlags fromDate:(NSDate *)date; //创建日期 NSDate?*d = [NSDate?date]; //创建日期对象 NSCalendar?*ca =

IOS中级篇——何时使用copy,strong,weak,assign关键字 定义属性

? 父类指针可以指向子类对象 ? //定义block别名. typedef void (^LYItemOption)(); @interface LYItemArrow : LYItem@property(nonatomic,strong) Class desController; @property(nonatomic,copy) LYItemOption option; ? ? 1.strong :除NSString\block以外的OC对象 ? @property(nonatomic,st

IOS中级篇 —— Autoresizing

? UIView *blueView = [[UIView alloc] init]; ??? [self.view addSubview:blueView]; ??? blueView.backgroundColor = [UIColor blueColor]; ??? ??? blueView.center = self.view.center; ??? blueView.bounds = CGRectMake(0, 0, 150, 150); ??? self.blueView = blu

IOS中级篇 —— 关于深复制和浅复制

?深复制(深拷贝,内容拷贝,deep?copy) ?源对象和副本对象是不同的两个对象 ?源对象引用计数器不变,?副本对象计数器为1(因为是新产生的) ?本质是:产生了新的对象 ? ?浅复制(浅拷贝,指针拷贝,shallow?copy) ?源对象和副本对象是同一个对象 ?源对象(副本对象)引用计数器?+?1,?相当于做一次retain操作 ?本质是:没有产生新的对象

IOS中级篇 —— 手动内存管理

retainCount?? //dealloc方法,是对象的临终遗言的方法 //对象被销毁的时候,会默认的调用该方法 //注意:dealloc 方法是系统根据引用计数器的值,自动调用的, 野指针 内存泄露 @property??参数 @class 使用 循环retain解决方法 自动释放池?? @autoreleasepool

IOS中级篇 —— NSFileManager常用方法

[fileManager isDeletableFileAtPath:<#(NSString *)#>]; 判断一个路径是否可删除 [fileManager isWritableFileAtPath:<#(NSString *)#>];??判断一个路径是否可写 [fileManager isReadableFileAtPath:<#(NSString *)#>];??判断一个路径是否可读 [fileManager fileExistsAtPath:<#(NSStr