OC中的代码块是iOS4.0+ 和Mac OS X 10.6+ 引进的对C语言的扩展,用来实现匿名函数的特性。类似于其他语言脚本语言或者编程语言中的闭包或者是Lambda表达式,可能第一眼看上去很怪异,不过开发的过程中会越来越多的用到Block,还是了解多一点比较好。Block方面的内容也有很多,本文从实际使用的角度大概讲一下Block的基本概念和实践。
首先看一个苹果官网的例子:
1
2
3
4
|
int
(^Multiply)(
int
,
int
) = ^(
int
num1,
int
num2) {
return
num1 * num2;
};
int
result = Multiply(7, 4);
// Result is 28.
|
上面的代码定义了一个Block,类似于C#中的委托,int表示返回类型,^是关键标示符,(int,int)是参数类型,不过需要注意的,正常的方式是将返回类型用()包裹,这里是将Block的名称包裹,网上有一个类似的图片,大家可以参考一下:
Block除了能够定义参数列表、返回类型外,还能够获取被定义时的词法范围内的状态(将变量作为参数传递之后,可以修改之后返回).Block都是一些简短代码片段的封装,适用作工作单元,通常用来做并发任务、遍历、以及回调。下面看一个通知的例子:
1
2
3
4
5
6
7
8
9
10
|
- (
void
)viewDidLoad {
[
super
viewDidLoad];
[[
NSNotificationCenter
defaultCenter] addObserver:
self
selector:
@selector
(keyboardWillShow:)
name:UIKeyboardWillShowNotification object:
nil
];
}
- (
void
)keyboardWillShow:(
NSNotification
*)notification {
// Notification-handling code goes here.
}
|
以上是调用addServer方法的例子,不过也可以这么写:
1
2
3
4
5
6
7
|
- (
void
)viewDidLoad {
[
super
viewDidLoad];
[[
NSNotificationCenter
defaultCenter] addObserverForName:UIKeyboardWillShowNotification
object:
nil
queue:[
NSOperationQueue
mainQueue] usingBlock:^(
NSNotification
*notif) {
// Notification-handling code goes here.
}];
}
|
苹果官网这个使用Block的例子如果第一次看可能不是那么好理解,如果仔细的看addServerName的定义发现:
1
|
- (
id
<
NSObject
>)addObserverForName:(
NSString
*)name object:(
id
)obj queue:(
NSOperationQueue
*)queue usingBlock:(
void
(^)(
NSNotification
*note))block
NS_AVAILABLE
(10_6, 4_0);
|
其中Block参数定义的时候是这样的:
1
|
(
void
(^)(
NSNotification
*note))block
NS_AVAILABLE
(10_6, 4_0)
|
括号包裹起来的内容,第一个是返回值类型,之后的用用括号包裹^,之后的 话才是传递类型,基于以上的理解,可以这么写:
1
2
3
4
5
|
void
(^MyBlock)(
NSNotification
*)=^(
NSNotification
*note){
note=
nil
;
};
[[
NSNotificationCenter
defaultCenter] addObserverForName:UIKeyboardWillShowNotification
object:
nil
queue:[
NSOperationQueue
mainQueue] usingBlock:MyBlock];
|
Block在苹果的API文档中随处看见其身影,常见的情况任务完成时回调处理,消息监听回调处理,错误回调处理,枚举回调,视图动画、变换,排序,比如说在NSDictionary中的方法中:
1
|
- (
void
)enumerateKeysAndObjectsWithOptions:(
NSEnumerationOptions
)opts usingBlock:(
void
(^)(
id
key,
id
obj,
BOOL
*stop))block
NS_AVAILABLE
(10_6, 4_0);
|
任务完成时候的调用:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
- (
IBAction
)animateView:(
id
)sender {
CGRect cacheFrame =
self
.imageView.frame;
[UIView animateWithDuration:1.5 animations:^{
CGRect newFrame =
self
.imageView.frame;
newFrame.origin.y = newFrame.origin.y + 150.0;
self
.imageView.frame = newFrame;
self
.imageView.alpha = 0.2;
}
completion:^ (
BOOL
finished) {
if
(finished) {
// Revert image view to original.
self
.imageView.frame = cacheFrame;
self
.imageView.alpha = 1.0;
}
}];
}
|
通知机制中的处理:
1
2
3
4
5
6
7
8
9
|
- (
void
)applicationDidFinishLaunching:(
NSNotification
*)aNotification {
opQ = [[
NSOperationQueue
alloc] init];
[[
NSNotificationCenter
defaultCenter] addObserverForName:@
"CustomOperationCompleted"
object:
nil
queue:opQ
usingBlock:^(
NSNotification
*notif) {
NSNumber
*theNum = [notif.userInfo objectForKey:@
"NumberOfItemsProcessed"
];
NSLog
(@
"Number of items processed: %i"
, [theNum intValue]);
}];
}
|
枚举数组的时候的调用:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
NSString
*area = @
"Europe"
;
NSArray
*timeZoneNames = [
NSTimeZone
knownTimeZoneNames];
NSMutableArray
*areaArray = [
NSMutableArray
arrayWithCapacity:1];
NSIndexSet
*areaIndexes = [timeZoneNames indexesOfObjectsWithOptions:
NSEnumerationConcurrent
passingTest:^(
id
obj,
NSUInteger
idx,
BOOL
*stop) {
NSString
*tmpStr = (
NSString
*)obj;
return
[tmpStr hasPrefix:area];
}];
NSArray
*tmpArray = [timeZoneNames objectsAtIndexes:areaIndexes];
[tmpArray enumerateObjectsWithOptions:
NSEnumerationConcurrent
|
NSEnumerationReverse
usingBlock:^(
id
obj,
NSUInteger
idx,
BOOL
*stop) {
[areaArray addObject:[obj substringFromIndex:[area length]+1]];
}];
NSLog
(@
"Cities in %@ time zone:%@"
, area, areaArray);
|
也可以写一个Block在截取字符串,做一些自己需要的事情:
1
2
3
4
5
6
7
8
9
10
11
12
|
NSString
*musician = @
"Beatles"
;
NSString
*musicDates = [
NSString
stringWithContentsOfFile:
@
"/usr/share/calendar/calendar.music"
encoding:
NSASCIIStringEncoding
error:
NULL
];
[musicDates enumerateSubstringsInRange:
NSMakeRange
(0, [musicDates length]-1)
options:
NSStringEnumerationByLines
usingBlock:^(
NSString
*substring,
NSRange
substringRange,
NSRange
enclosingRange,
BOOL
*stop) {
NSRange
found = [substring rangeOfString:musician];
if
(found.location !=
NSNotFound
) {
NSLog
(@
"%@"
, substring);
}
}];
|
视图动画和转换中的实践:
1
2
3
4
5
|
[UIView animateWithDuration:0.2 animations:^{
view.alpha = 0.0;
} completion:^(
BOOL
finished){
[view removeFromSuperview];
}];
|
两个视图之间的动画:
1
2
3
4
5
6
7
|
[UIView transitionWithView:containerView duration:0.2
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:^{
[fromView removeFromSuperview];
[containerView addSubview:toView]
}
completion:
NULL
];
|
数组排序的实践:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
NSArray
*stringsArray = [
NSArray
arrayWithObjects:
@
"string 1"
,
@
"String 21"
,
@
"string 12"
,
@
"String 11"
,
@
"String 02"
,
nil
];
static
NSStringCompareOptions
comparisonOptions =
NSCaseInsensitiveSearch
|
NSNumericSearch
|
NSWidthInsensitiveSearch
|
NSForcedOrderingSearch
;
NSLocale
*currentLocale = [
NSLocale
currentLocale];
NSComparator
finderSort = ^(
id
string1,
id
string2) {
NSRange
string1Range =
NSMakeRange
(0, [string1 length]);
return
[string1 compare:string2 options:comparisonOptions range:string1Range locale:currentLocale];
};
NSLog
(@
"finderSort: %@"
, [stringsArray sortedArrayUsingComparator:finderSort]);
|
本文转自Fly_Elephant博客园博客,原文链接:http://www.cnblogs.com/xiaofeixiang/p/4254879.html,如需转载请自行联系原作者