文档章节

NSOperation 简介和应用

云飞扬v5
 云飞扬v5
发布于 2016/11/12 16:07
字数 1633
阅读 1
收藏 0
点赞 0
评论 0

基本介绍

NSBlockOperation

 

- (void)singleBlockOperation{
    NSLog(@"thread == %@ 1",[NSThread currentThread]);
    NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^(){
         NSLog(@"thread == %@ doing a operation",[NSThread currentThread]);
        
    }];
    // 开始执行任务
    NSLog(@"thread == %@ 2",[NSThread currentThread]);
    
    [operation start];
    
    NSLog(@"thread == %@ after operation",[NSThread currentThread]);
    
    
}

打印内容

2016-11-12 10:17:13.001 MutipleThreadPractice[77168:3862880] thread == <NSThread: 0x7f9451704800>{number = 1, name = main} 1
2016-11-12 10:17:13.002 MutipleThreadPractice[77168:3862880] thread == <NSThread: 0x7f9451704800>{number = 1, name = main} 2
2016-11-12 10:17:13.002 MutipleThreadPractice[77168:3862880] thread == <NSThread: 0x7f9451704800>{number = 1, name = main} doing a operation
2016-11-12 10:17:13.002 MutipleThreadPractice[77168:3862880] thread == <NSThread: 0x7f9451704800>{number = 1, name = main} after operation

 

- (void)multipleBlockOperation{
    
    NSLog(@"thread== %@ start", [NSThread currentThread]);
    NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^(){
        NSLog(@"thread== %@ 1", [NSThread currentThread]);
    }];
    
    [operation addExecutionBlock:^() {
        NSLog(@"thread== %@ 2", [NSThread currentThread]);
    }];
    
    [operation addExecutionBlock:^() {
        NSLog(@"thread== %@ 3", [NSThread currentThread]);
    }];
    
    [operation addExecutionBlock:^() {
        NSLog(@"thread== %@ 4", [NSThread currentThread]);
    }];
    
    
    NSLog(@"thread== %@ 5", [NSThread currentThread]);
    // 开始执行任务
    [operation start];
    
    
    NSLog(@"thread== %@ 6", [NSThread currentThread]);

}

打印纪录

 

2016-11-12 10:23:59.998 MutipleThreadPractice[77537:3867741] thread== <NSThread: 0x7fb4f16040c0>{number = 1, name = main} start
2016-11-12 10:23:59.998 MutipleThreadPractice[77537:3867741] thread== <NSThread: 0x7fb4f16040c0>{number = 1, name = main} 5
2016-11-12 10:23:59.998 MutipleThreadPractice[77537:3867741] thread== <NSThread: 0x7fb4f16040c0>{number = 1, name = main} 1
2016-11-12 10:23:59.998 MutipleThreadPractice[77537:3867741] thread== <NSThread: 0x7fb4f16040c0>{number = 1, name = main} 2
2016-11-12 10:23:59.999 MutipleThreadPractice[77537:3867741] thread== <NSThread: 0x7fb4f16040c0>{number = 1, name = main} 4
2016-11-12 10:23:59.999 MutipleThreadPractice[77537:3869224] thread== <NSThread: 0x7fb4f1719040>{number = 4, name = (null)} 3
2016-11-12 10:24:00.001 MutipleThreadPractice[77537:3867741] thread== <NSThread: 0x7fb4f16040c0>{number = 1, name = main} 6

 

取消操作

[operation cancel];

 

NSOperation的依赖关系

MyDownloadOperation *downloadOp = [[MyDownloadOperation alloc] init]; // MyDownloadOperation is a subclass of NSOperation
MyFilterOperation *filterOp = [[MyFilterOperation alloc] init]; // MyFilterOperation  is a subclass of NSOperation
         
[filterOp addDependency:downloadOp];

要删除依赖性:
[filterOp removeDependency:downloadOp];

 

执行完block后进行的操作

    operation.completionBlock = ^() {
        NSLog(@"执行完毕");
    };

 

NSOperationQueue

NSOperationQueue *myQueue = [[NSOperationQueue alloc] init];
myQueue.name = @"Download Queue";

并发操作的最大值:

你可以设定NSOperationQueue可以并发运行的最大操作数。NSOperationQueue会选择去运行任何数量的并发操作,但是不会超过最大值。

myQueue.MaxConcurrentOperationCount = 3;

如果你改变了主意,想将MaxConcurrentOperationCount设置回默认值,你可以执行下列操作:

myQueue.MaxConcurrentOperationCount = NSOperationQueueDefaultMaxConcurrentOperationCount; 

 

待处理的操作:

任何时候你可以询问一个队列哪个操作在里面,并且总共有多少个操作在里面。记住只有那些等待被执行的操作,还有那些正在运行的操作,会被保留在队列中。操作一完成,就会退出队列。 
NSArray *active_and_pending_operations = myQueue.operations;
NSInteger count_of_operations = myQueue.operationCount; 

 

暂停队列:你可以通过设定setSuspended:YES来暂停一个队列。这样会暂停所有在队列中的操作 — 你不能单独的暂停操作。要重新开始队列,只要简单的setSuspended:NO。 
// Suspend a queue
[myQueue setSuspended:YES];
.
.
.
// Resume a queue
[myQueue setSuspended: NO]; 

取消操作:要取消一个队列中的所有操作,你只要简单的调用“cancelAllOperations”方法即可。还记得之前提醒过经常检查NSOperation中的isCancelled属性吗?

 

UIImage *myImage = nil;
 
// Create a weak reference
__weak UIImage *myImage_weak = myImage;
 
// Add an operation as a block to a queue
[myQueue addOperationWithBlock: ^ {
 
    // a block of operation
    NSURL *aURL = [NSURL URLWithString:@"http://www.somewhere.com/image.png"];
    NSError *error = nil;
    NSData *data = [NSData dataWithContentsOfURL:aURL options:nil error:&error];
    If (!error)
        [myImage_weak imageWithData:data];
 
    // Get hold of main queue (main thread)
    [[NSOperationQueue mainQueue] addOperationWithBlock: ^ {
        myImageView.image = myImage_weak; // updating UI
    }];
 
}]; 

 

 

 

自定义NSOperation

自定义了一个NSOperation的子类,然后重写main方法。并定义了一个代理方法,用来处理Operation执行完毕后的操作。

 

 

app.plist的内容

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
	<dict>
		<key>icon</key>
		<string>http://zbimg.25pp.com/images/artwork/102/951610982_54x54.jpg</string>
		<key>name</key>
		<string>菜鸟裹裹</string>
		<key>download</key>
		<string></string>
	</dict>
	<dict>
		<key>icon</key>
		<string>http://zbimg.25pp.com/images/artwork/92/855031900_54x54.jpg</string>
		<key>name</key>
		<string>十六番</string>
		<key>download</key>
		<string></string>
	</dict>
	<dict>
		<key>icon</key>
		<string>http://zbimg.25pp.com/images/artwork/246/950137846_54x54.jpg</string>
		<key>name</key>
		<string>暴风魔镜Pro</string>
		<key>download</key>
		<string></string>
	</dict>
	<dict>
		<key>icon</key>
		<string>http://zbimg.25pp.com/images/artwork/189/1044569021_54x54.jpg</string>
		<key>name</key>
		<string>斗图神器</string>
		<key>download</key>
		<string></string>
	</dict>
	<dict>
		<key>icon</key>
		<string>http://zbimg.25pp.com/images/artwork/80/1048881232_54x54.jpg</string>
		<key>name</key>
		<string>糖果工厂</string>
		<key>download</key>
		<string></string>
	</dict>
	<dict>
		<key>icon</key>
		<string>http://zbimg.25pp.com/images/artwork/110/656554606_54x54.jpg</string>
		<key>name</key>
		<string>念力移物</string>
		<key>download</key>
		<string></string>
	</dict>
	<dict>
		<key>icon</key>
		<string>http://zbimg.25pp.com/images/artwork/218/904209370_54x54.jpg</string>
		<key>name</key>
		<string>B612</string>
		<key>download</key>
		<string></string>
	</dict>
</array>
</plist>

 

YYModel.h

#import <Foundation/Foundation.h>

@interface YYappModel : NSObject

/**
 *应用名称
 */
@property(nonatomic,copy)NSString *name;
/**
 *  应用图片
 */
@property(nonatomic,copy)NSString *icon;
/**
 *  应用的下载量
 */
@property(nonatomic,copy)NSString *download;

+(instancetype)appModelWithDict:(NSDictionary *)dict;
-(instancetype)initWithDict:(NSDictionary *)dict;

@end

 

YYModel.m

#import "YYappModel.h"

@implementation YYappModel

-(instancetype)initWithDict:(NSDictionary *)dict
{
    if (self=[super init]) {
        [self setValuesForKeysWithDictionary:dict];
    }
    return self;
}

//工厂方法
+(instancetype)appModelWithDict:(NSDictionary *)dict
{
    return [[self alloc]initWithDict:dict];
}

@end

 

YYdownLoadOperation.h

#import <Foundation/Foundation.h>
#pragma mark -设置代理和代理方法
@class YYdownLoadOperation;
@protocol YYdownLoadOperationDelegate <NSObject>
- (void)downLoadOperation:(YYdownLoadOperation *)operation
        didFishedDownLoad:(UIImage *)image;

@end

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

 

YYdownLoadOperation.m

#import "YYdownLoadOperation.h"

@implementation YYdownLoadOperation
-(void)main
{
    NSURL *url=[NSURL URLWithString:self.url];
    NSData *data=[NSData dataWithContentsOfURL:url];
    UIImage *imgae=[UIImage imageWithData:data];
    
    NSLog(@"--%@--",[NSThread currentThread]);
    //图片下载完毕后,通知代理
    if ([self.delegate respondsToSelector:@selector(downLoadOperation:didFishedDownLoad:)]) {
        dispatch_async(dispatch_get_main_queue(), ^{//回到主线程,传递数据给代理对象
            [self.delegate downLoadOperation:self didFishedDownLoad:imgae];
        });
    }
}
@end

 

CustomOperationDemoViewController.h

 

#import <UIKit/UIKit.h>

@interface CustomOperationDemoViewController : UIViewController

@end

 

CustomOperationDemoViewController.m


#import "CustomOperationDemoViewController.h"
#import "YYappModel.h"
#import "YYdownLoadOperation.h"
@interface CustomOperationDemoViewController ()
<YYdownLoadOperationDelegate,UITableViewDataSource,UITableViewDelegate>

@property(nonatomic,strong)NSArray *apps;

@property(nonatomic,strong)NSOperationQueue *queue;

@property (nonatomic,strong) UITableView *tableView;


@property(nonatomic,strong)NSMutableDictionary *operations;
@property(nonatomic,strong)NSMutableDictionary *images;
@end

@implementation CustomOperationDemoViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self.view addSubview:self.tableView];
    
    [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.equalTo(self.view);
    }];
    
    
    // Do any additional setup after loading the view.
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

-(NSArray *)apps
{
    if (_apps==nil) {
        NSString *path=[[NSBundle mainBundle]pathForResource:@"apps.plist" ofType:nil];
        NSArray *tempArray=[NSArray arrayWithContentsOfFile:path];
        
        //字典转模型
        NSMutableArray *array=[NSMutableArray array];
        for (NSDictionary *dict in tempArray) {
            YYappModel *app=[YYappModel appModelWithDict:dict];
            [array addObject:app];
        }
        _apps=array;
    }
    return _apps;
}

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

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

}

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

}

- (UITableView *)tableView{
    if(!_tableView){
        _tableView = [[UITableView alloc]init];
        _tableView.dataSource =self;
        _tableView.delegate = self;
    }
    return _tableView;

}

#pragma mark-数据源方法
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.apps.count;
}


-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *ID=@"ID";
    UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:ID];
    if (cell==nil) {
        cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
    }
    YYappModel *app=self.apps[indexPath.row];
    cell.textLabel.text=app.name;
    cell.detailTextLabel.text=app.download;
    
    //保证一个url对应一个image对象
    UIImage *image=self.images[app.icon];
    if (image) {//缓存中有图片
        cell.imageView.image=image;
    }else       //  缓存中没有图片,得下载
    {
        //先设置一张占位图片
        cell.imageView.image=[UIImage imageNamed:@"57437179_42489b0"];
        YYdownLoadOperation *operation=self.operations[app.icon];
        if (operation) {//正在下载
            //什么都不做
        }else  //当前没有下载,那就创建操作
        {
            operation=[[YYdownLoadOperation alloc]init];
            operation.url=app.icon;
            operation.indexPath=indexPath;
            operation.delegate=self;
            [self.queue addOperation:operation];//异步下载
            self.operations[app.icon]=operation;
        }
    }
    
    
    return cell;
}
-(void)downLoadOperation:(YYdownLoadOperation *)operation didFishedDownLoad:(UIImage *)image
{
    //1.移除执行完毕的操作
    [self.operations removeObjectForKey:operation.url];
    
    //2.将图片放到缓存中
    self.images[operation.url]=image;
    
    //3.刷新表格(只刷新下载的那一行)
    
    [self.tableView reloadRowsAtIndexPaths:@[operation.indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
    NSLog(@"--%d--%@--",operation.indexPath.row,[NSThread currentThread]);
    
}


 

@end

 

 

参考资料

 

iOS开发多线程篇—自定义NSOperation

http://www.cnblogs.com/wendingding/p/3811121.html

 

多线程编程2-NSOperation

http://www.cnblogs.com/mjios/archive/2013/04/19/3029765.html

 

如何使用NSOperations和NSOperationQueues(二)

http://www.cocoachina.com/industry/20121010/4900.html

© 著作权归作者所有

共有 人打赏支持
云飞扬v5
粉丝 11
博文 74
码字总数 67465
作品 0
金华
iOS多线程之NSOperation

1.简介 1.1NSOperation的作用 配合使用NSOperation和NSOperationQueue也能实现多线程编程 1.2NSOperation和NSOperationQueue实现多线程的具体步骤 先将需要执行的操作封装到一个NSOperation...

JlongTian ⋅ 2016/01/10 ⋅ 0

iOS开发 多线程(三)转自MJ的NSOperationQueue使用

一、简介 一个NSOperation对象可以通过调用start方法来执行任务,默认是同步执行的。也可以将NSOperation添加到一个NSOperationQueue(操作队列)中去执行,而且是异步执行的。 创建一个操作队...

神补刀 ⋅ 2015/08/18 ⋅ 0

iOS之[多线程:NSOperation]

NSOperation :fa-exclamation-triangle:以下是你需要考虑使用 NSOperation 的一些理由: 1.当你需要取消线程任务时,GCD 无法提供取消任务的操作。而 NSOperation 提供了取消任务的操作; 2.当...

言筱羽 ⋅ 2015/11/23 ⋅ 0

多线程NSOperation一般使用

一、NSOperation简介 简单说明 NSOperation的作⽤:配合使用NSOperation和NSOperationQueue也能实现多线程编程 NSOperation和NSOperationQueue实现多线程的具体步骤: (1)先将需要执行的操...

朝雨晚风 ⋅ 2016/08/22 ⋅ 0

iOS多线程的实现方案

技术方案 简介 语言 生命周期 使用频率 NSThread 使用更加面向对象 简单实用,可直接操作线程对象 OC 程序猿管理 偶尔使用 GCD 旨在替代NSThread等线程技术 充分利用设备的多核 C 自动管理 ...

JlongTian ⋅ 2016/01/07 ⋅ 0

并发程序设计——Operation Queues(操作队列)

Cocoa operations以面向对象的形式封装程序中的工作单元,提供异步执行机制。Operations可以独立运行,也可以与Operation Queue协同运行。OS X和IOS中Cocoa应用程序大多运用了operation机制。...

big军 ⋅ 2013/06/04 ⋅ 0

iOS多线程:『NSOperation、NSOperationQueue』详尽总结

iOS多线程:『NSOperation、NSOperationQueue』详尽总结 转载: 原地址https://www.jianshu.com/p/4b1d77054b35 本文首发于我的个人博客:『不羁阁』 文章链接:传送门 本文更新时间:2018年0...

法斗斗 ⋅ 04/20 ⋅ 0

iOS学习 --多线程和GCD的理解

进程的概念:每一个进程都是一个应用程序,都有独立的内存空间,一般情况下,一个应用存在一个进程,但也有多个进程的情况(比如浏览器) 同一个进程中的线程共享内存中的内存和资源。 多线程...

fengyun321 ⋅ 2015/09/20 ⋅ 0

多线程 NSThread,NSOperation,GCD

iOS中的线程 iOS主线程(UI线程),我们的大部分业务逻辑代码运行于主线程中。 没有特殊需求,不应引入线程增加程序复杂度。 应用场景:逻辑执行时间过长,严重影响交互体验(界面卡死)等。 iOS多线...

HelloSwift ⋅ 2016/08/08 ⋅ 0

玩转iOS开发:iOS中的NSOperation开发(一)

文章分享至我的个人技术博客: cainrun.github.io/15019481375… 之前, 我们花了小段时间就把给摸了个底, 知道了的操作, 不知道大家有没有好好去耍耍, 这次我们再来讲讲, 中的多线程操作. , 它...

CainLuo ⋅ 2017/08/14 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Spring Bean基础

1、Bean之间引用 <!--如果Bean配置在同一个XML文件中,使用local引用--><ref bean="someBean"/><!--如果Bean配置在不同的XML文件中,使用ref引用--><ref local="someBean"/> 其实两种......

霍淇滨 ⋅ 13分钟前 ⋅ 0

05、基于Consul+Upsync+Nginx实现动态负载均衡

1、Consul环境搭建 下载consul_0.7.5_linux_amd64.zip到/usr/local/src目录 cd /usr/local/srcwget https://releases.hashicorp.com/consul/0.7.5/consul_0.7.5_linux_amd64.zip 解压consu......

北岩 ⋅ 16分钟前 ⋅ 0

Webpack 4 api 了解与使用

webpack 最近升级到了 v4.5+版 01 官方不再支持 node4 以下版本 官方不再支持 node4 以下版本官方不再支持 node4 以下的版本,所以如果你的node版本太低,先开始升级node吧!话说node10 ...

NDweb ⋅ 26分钟前 ⋅ 0

使用nodeJs安装Vue-cli

Vue脚手架就是一个Vue框架开发环境 脚手架的意思是帮你快速开始一个vue的项目,也就是给你一套vue的结构,包含基础的依赖库,只需要 npm install就可以安装,让我们不需要为了编辑或者一些其...

木筏笔歆 ⋅ 58分钟前 ⋅ 0

【微信小程序开发实战】0x00.开发前准备工作

写在开始 本人资深后端码农一枚,近期项目需求,接触到了微信小程序,将学习过程整理成文分享给小伙伴们,由于是边学边整理难免有表述不对的地方,望大家及时指正,感谢。 本人微信号: dream...

dreamans ⋅ 今天 ⋅ 0

linux redis的安装和php7下安装redis扩展

安装redis服务器 (1)下载安装包: $ wget http://download.redis.io/releases/redis-2.8.17.tar.gz (2)编译程序: $ tar xzf redis-2.8.17.tar.gz $ cd redis-2.8.17 $ make $ cd src &&......

concat ⋅ 今天 ⋅ 0

Guava EventBus源码解析

一、EventBus使用场景示例 Guava EventBus是事件发布/订阅框架,采用观察者模式,通过解耦发布者和订阅者简化事件(消息)的传递。这有点像简化版的MQ,除去了Broker,由EventBus托管了订阅&...

SaintTinyBoy ⋅ 今天 ⋅ 0

http怎么做自动跳转https

Apache 版本 如果需要整站跳转,则在网站的配置文件的<Directory>标签内,键入以下内容: RewriteEngine on RewriteCond %{SERVER_PORT} !^443$ RewriteRule ^(.*)?$ https://%{SERVER_NAME......

Helios51 ⋅ 今天 ⋅ 0

Python爬虫,抓取淘宝商品评论内容

作为一个资深吃货,网购各种零食是很频繁的,但是能否在浩瀚的商品库中找到合适的东西,就只能参考评论了!今天给大家分享用python做个抓取淘宝商品评论的小爬虫! 思路 我们就拿“德州扒鸡”...

python玩家 ⋅ 今天 ⋅ 0

MySQL 内核深度优化

MYSQL数据库适用场景广泛,相较于Oracle、DB2性价比更高,Web网站、日志系统、数据仓库等场景都有MYSQL用武之地,但是也存在对于事务性支持不太好(MySQL 5.5版本开始默认引擎才是InnoDB事务...

java高级架构牛人 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部