上一篇文章稍微提及了一下NSThread的使用,NSThread能直观地控制线程对象,不过需要自己管理线程的生命周期,线程同步,用起来比较繁琐,而且比较容易出错。不过Apple给出了自己的解决方案NSOperation,它本身是抽象基类,因此必须使用它的子类,使用NSOperation子类的方式有NSInvocationOperation和NSBlockOperation两种方式,先补充一下NSThread的用法:
NSThread获取当前线程:
1
|
[
NSThread
currentThread]
|
performSelectorInBackground可以更新UI,不建议使用:
1
2
3
4
5
|
- (
IBAction
)update:(
id
)sender {
[
self
performSelectorInBackground:
@selector
(changeImage) withObject:
nil
];
}
|
图片背景更新:
1
2
3
4
|
-(
void
)changeImage{
NSLog
(@
"线程执行完之后更新图片"
);
self
.myImageView.image=[UIImage imageNamed:[
NSString
stringWithFormat:@
"Thread2.jpg"
]];
}
|
NSInvocationOperation和NSBlockOperation
这两种方式都很简单,其中NSInvocation的调用方式类似于NSThread,NSBlockOperation如果对Block有一点了解就可以,如果不明白的可以参考本人之前的Block文章 Object-C-代码块Block回顾,那么接下来的使用方式就很简单:
先来看下NSInvocationOperation的实例化方式:
1
2
3
4
|
//初始化
NSInvocationOperation
*myInvocationOperation= [[
NSInvocationOperation
alloc] initWithTarget:
self
selector:
@selector
(operationTaskMethod) object:
nil
];
//启动
[myInvocationOperation start];
|
调用方法:
1
2
3
4
|
-(
void
)operationTaskMethod{
NSLog
(@
"NSInvocationOperation初始化执行"
);
}
|
NSBlockOperation的方式:
1
2
3
4
|
NSBlockOperation
*blockOperation=[
NSBlockOperation
blockOperationWithBlock:^{
NSLog
(@
"BlockOperation块执行"
);
}];
[blockOperation start];
|
两种方式很方便,这个时候可以使用NSOperationQueue作为一个队列将线程包含在一起,首先定义一个NSOperationQuene:
1
|
@property
(strong,
nonatomic
)
NSOperationQueue
*myOperationQuene;
|
这个时候需要调用:
1
2
3
4
5
6
7
8
9
10
11
|
NSInvocationOperation
*myInvocationOperation= [[
NSInvocationOperation
alloc] initWithTarget:
self
selector:
@selector
(operationTaskMethod) object:
nil
];
NSBlockOperation
*blockOperation=[
NSBlockOperation
blockOperationWithBlock:^{
NSLog
(@
"BlockOperation块执行"
);
}];
self
.myOperationQuene=[[
NSOperationQueue
alloc]init];
[
self
.myOperationQuene addOperation:myInvocationOperation];
[
self
.myOperationQuene addOperation:blockOperation];
|
上面最后的结果不确定,线程执行的顺序没法确定,如果想确定的按照顺序执行,需要添加一个依赖:
1
|
[blockOperation addDependency:myInvocationOperation];
|
添加依赖之后的,每次输出的结果一定是这样的:
1
2
|
2015-02-11 07:56:13.457 ThreadDemo[657:15033]
NSInvocationOperation
初始化执行
2015-02-11 07:56:13.457 ThreadDemo[657:15034] BlockOperation块执行
|
自定义NSOperation
每次一看到自定义,就感觉瞬间有了档次,然后参考一下前人的经验,不过网上的博客有的不好说,那感觉就是我想吃一个鸡腿,却拿到了一个鸡腿堡,需要的不需要的都要自己一起吸收。NSInvocationOperation和NSBlockOperation这两种方式不能满足业务需求,这个时候需要自定义的NSOperation,自定义的有两种分为非并发(NonConcurrent)和并发(Concurrent)两种形式,本文介绍非并发形式。
新建一个继承自NSOperation的MyCustomOperation,然后实现一下main方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
//
// MyCustomOperation.h
// ThreadDemo
//
// Created by keso on 15/2/11.
// Copyright (c) 2015年 keso. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface
MyCustomOperation :
NSOperation
@property
(strong,
nonatomic
)
NSString
*customdata;
-(
void
)initData:(
NSString
*)data;
@end
|
NSOperation对象需要定期地调用isCancelled方法检测操作是否已经被取消,如果返回YES(表示已取消),则立即退出执行回收内存资源。所有NSOperation子类,一般用于代码比较容易终止的地方, 在循环的每次迭代过程中,如果每个迭代相对较长可能需要调用多次和没有执行工作之前调用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
//
// MyCustomOperation.m
// ThreadDemo
//
// Created by keso on 15/2/10.
// Copyright (c) 2015年 keso. All rights reserved.
//
#import "MyCustomOperation.h"
@implementation
MyCustomOperation
- (
void
)initData:(
NSString
*)data{
if
(
self
==[
super
init])
_customdata= data;
}
- (
void
)main {
@try
{
BOOL
isDone =
NO
;
NSLog
(@
"循环之前的调用"
);
while
(![
self
isCancelled] && !isDone) {
// Do some work and set isDone to YES when finished
NSLog
(@
"已经运行成功了"
);
isDone=
YES
;
}
}
@catch
(...) {
NSLog
(@
"出现异常,请检查代码~"
);
}
}
@end
|
如果需要调用定义的NSOPeration实例化之后Start即可:
1
2
|
MyCustomOperation *customOperation=[[MyCustomOperation alloc] init];
[customOperation start];
|
本文转自Fly_Elephant博客园博客,原文链接:http://www.cnblogs.com/xiaofeixiang/p/4285102.html,如需转载请自行联系原作者