代码块(Block)的使用
来源:互联网 发布:衡水数控编程招聘信息 编辑:程序博客网 时间:2024/06/05 08:15
一、Block简介
Block:即块语法,本质上是匿名函数(没有名称的函数),标准C⾥⾯没有Block,C语⾔的后期扩展版本,加⼊了匿名函数,在C++、JS、Swift等语⾔,有类似语法,叫做闭包。Block语法和函数指针很相似。
因为Block是匿名函数,block变量存放的函数的实现,所以我们可以通过block变量直接调⽤函数。
二、 Block详细
如下图:
(图片摘自http://blog.csdn.net/totogo2010/article/details/7839061)
分析:
由图可以分析 Block的类型:int (^)(int) -->可以和函数指针做类比
Block变量:myBlock
Block值:^ int (int num){ return 7 * num;}
即:^ 返回值类型 (参数列表){函数体} 其中 返回值类型 可以省略。
Block变量:myBlock
Block值:^ int (int num){ return 7 * num;}
即:^ 返回值类型 (参数列表){函数体} 其中 返回值类型 可以省略。
1. Block基本使用
以下Block实现将字符串转换为数字,并返回。
int (^myBlock)(NSString*); myBlock = ^(NSString* numStr) { return [numStr intValue]; };
调用Block
NSLog(@"%d", myBlock(@"123"));
2. 用 typedef 命名 Block
我们知道,在定义函数指针的时候,直接定义指针很麻烦,而且可读性也不好。所以一般我们都用 typedef 先把函数指针类型定义成新的名称,以方便使用。在定义 Block 时也一样,我们可以借助 typedef 来给 Block 类型定义新的名称。如下:
typedef int(^BlockType)(int x, int y)
经过定义之后,BlockType 就是 int (^)(int x,int y) 类型了。如下定义:
typedef int (^BlockType)(int x,int y); BlockType myBlock = ^(int x, int y) { return x+y; }; NSLog(@"%d", myBlock(3, 4));
运行结果:7
3. Block实现字符串排序
NSArray *strArray = @[ @"bbb", @"aaa", @"ddd", @"ccc" ]; NSComparator sortedBlock = ^(NSString* s1, NSString* s2) { return [s1 compare : s2]; }; NSArray *newArray = [strArray sortedArrayUsingComparator:sortedBlock]; NSLog(@"newArray is : %@", newArray);
运行结果:
分析: NSComparator是什么类型?为什么能直接定义Block变量呢? 按住 command 键, 点击此类型进入 API 查看,如下:
typedef NSComparisonResult (^NSComparator)(id obj1, id obj2);可以看出,NSComparator就是块类型,即:NSComparisonResult^(id obj1, id obj2) 类型。所以以上的代码没问题。
4.Block 实现对象数组排序
如果一个数组存储的不是字符串,是其他的类对象(如Person类的对象),我们可以这样实现(以下代码按Person对象年龄排序):
Person *per1 = [[Person alloc] init]; per1.age = 20; Person *per2 = [[Person alloc] init]; per1.age = 18; Person *per3 = [[Person alloc] init]; per1.age = 22; NSArray *persons = [NSArray arrayWithObjects:per1, per2, per3, nil]; [persons sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) { Person *per1 = (Person*)obj1; Person *per2 = (Person*)obj2; if( per1.age > per2.age ) { return NSOrderedDescending; } else if ( per1.age < per2.age ) { return NSOrderedAscending; } else { return NSOrderedSame; } }];当然,你也可以像第三点的代码那样将 Block 抽取出来,即定义一个 Block 变量来存储。
5. Block 访问外部变量
在 Block 中,我们可以直接访问在其 外部的 局部变量,但是不允许修改变量的值, 如下:
a. 访问局部变量
int i = 3; typedef int (^BlockType)(int x,int y); BlockType myBlock = ^(int x, int y) { return i+x+y;<span style="white-space:pre"></span>//访问 i };
b. 修改局部变量, 如下图:
根据错误我们对代码做如下修改:
__block int i = 3; typedef int (^BlockType)(int x,int y); BlockType myBlock = ^(int x, int y) { i++; return i+x+y; };错误消失!!!
c. 访问并修改全局变量, 见代码:
int i = 3;int main(int argc, const char * argv[]){ typedef int (^BlockType)(int x,int y); BlockType myBlock = ^(int x, int y) { i++; return i+x+y; }; NSLog(@"%d", myBlock(3, 4));}
注:全局变量不允许声明为__block类型
6. Block 的递归调用
要想递归调用 Block, 则 Block变量 必须是全局变量或者静态变量。原因有博客说 “这样在程序启动的时候代码块变量就初始化了”
先看代码:
static int (^sumBlock)(int); //必须为静态变量 sumBlock = ^(int num) { int n = num-1; if( num <= 0 ) { return 0; } return num + sumBlock(n); }; NSLog(@"sum = %d", sumBlock(5));
我把 static 关键字去掉,然后后进行调试,发现如下图结果:
当程序运行到 Block 语句调用处时, sumBlock 有了如上图所示的内存地址,点击运行下一步
发现,这是后 sumBlock 为 NULL 了, 如果这时候再调用 sumBlock 程序肯定崩溃。而如果将 sumBlock定义成静态变量的话,我们知道静态变量是要等到整个程序运行结束才释放内存的,所以这时可以递归调用。
有个不明白的问题:如果 递归调用 非静态 Block 变量,当运行完 Block 调用处语句之后, sumBlock就会被释放并指向NULL, 而如果非递归调用 非静态 Block 变量,当运行完 Block 调用处语句之后,sumBlock 内存仍然存在(没被释放)。 实在搞不懂到底是为什么?
0 0
- 代码块(Block)的使用
- block代码块的使用
- block代码块的使用
- iOS开发-(^)代码块(block)的使用
- Objective-C语法之代码块(block)的使用
- IOS Block代码块的简单使用
- IOS Block代码块的简单使用
- iOS 代码块(block)的使用
- Block代码块的使用,和注意事项
- iOS中Block代码块的使用
- 关于Block代码块的使用
- iOS 代码块(block)的使用
- IOS Block 代码块使用 (一)
- IOS Block 代码块使用 (二)
- iOS 代码块(block)使用基础
- block代码块基础使用(一)
- 代码块(block)
- Objective-C语法之代码块(block)的使用
- 进程间通信IPC
- AFNetWorking 的简单使用
- 段奕宏演鬼谷子“没信心”
- Sofia-SIP辅助文档六 - Sofia-SIP中的SIP和SDP特性
- hdoj 1282 回文数猜想
- 代码块(Block)的使用
- poj 2222 Keywords Search,AC自动机模板题
- poj 2082 Terrible Sets
- NVIDIA Drivers Update Utility
- HDOJ 题目1086You can Solve a Geometry Problem too(数学)
- Lexmark Drivers Update Utility
- UVA - 488 Triangle Wave(水题)
- Lexmark Drivers Update Utility
- 【转载】linux-2.6.21 pi futex关键数据结构关系图及lock流程