Objective-C 14 代码块Block
来源:互联网 发布:mac添加农历 编辑:程序博客网 时间:2024/05/16 08:02
Blocks Block 代码段
Block封装了一段代码,可以在任何时候执行。它是对C语言中函数的扩展,它实际上是C语言实现的,所以它在各种以C作为基础的语言哪都是有效的,包括Objective-C、C++以及Objective-C++。
Block可以作为函数参数或者函数的返回值,而其本身又可以带输入参数或返回值。它和传统的函数指针很类似,但是有区别:
block是内联函数的,并且默认情况下它对局部变量是只读的。
苹果官方建议尽量多用block。在多线程、异步任务、集合遍历、集合排序、动画转场用的很多。
1 定义代码块
<returntype>(^blockname)(list of arguments) = ^returntype(arguments){body;};
编译器可以通过代码块的内容推导出返回类型,所以可以省略它。如果代码块中没有参数,也可以省略。
<returntype>(^blockname)(arguments) = ^(arguments){};
int (^Sum)(int, int) = ^(int a, int b){
return a+b;
}
=号前面是代码块的定义,而等号后面是实现内容。
定义了一个名叫Sum的block对象,带有两个int型参数,返回int。=式右边是block的具体实现。
2 使用代码块
int (^Sum)(int, int) = ^(int a, int b){ NSLog(@"block Sum 被调用了"); return a+b;};NSLog(@"调用Sum之前。");int a = Sum(2,22);NSLog(@"a=%i",a);
2016-02-25 19:14:46.709 命令行工程[924:132247] 调用Sum之前。2016-02-25 19:14:46.710 命令行工程[924:132247] block Sum 被调用了2016-02-25 19:14:46.710 命令行工程[924:132247] a=24
这样会固定block,只能使用Sum调用,我们可以通常使用typedef。
3 使用typedef关键字
typedef int (^MySum) (int, int);
//声明了一个block变量,类型为MySum。使用typedef可以声明无限多个block变量,方便使用。
#import <Foundation/Foundation.h>typedef int (^MySum)(int, int);int main(int argc, const char * argv[]) { @autoreleasepool { MySum sum1 = ^(int a, int b) { return a + b ; }; MySum sum2 = ^(int a, int b) { return a*b; }; NSLog(@"调用sum1 =%i",sum1(10,10)); NSLog(@"调用sum2 =%i",sum2(10,10)); } return 0;}输出:
2016-02-25 19:21:22.574 命令行工程[1002:135364] 调用sum1 =202016-02-25 19:21:22.575 命令行工程[1002:135364] 调用sum2 =100Program ended with exit code: 0
4 直接使用代码块
使用block通常不需要创建一个代码块变量,而是在代码中内联代码块的内容。
NSArray *stringArray = [NSArray arrayWithObjects:@"any", @"hello", @"body",@"good",@"cool",nil]; //升序排列 NSArray *sortedArray = [stringArray sortedArrayUsingComparator:^(id string1, id string2){ //NSLog(@"string1=%@,string2=%@",string1,string2); return [string1 compare:string2]; }]; NSLog(@"sortArray:%@", sortedArray);输出结果:
2016-08-15 14:34:06.257 命令行工程[1478:103112] sortArray:( any, body, cool, good, hello)
5 局部变量
typedef double (^SampleBlock)(void);double a1 = 10,b = 20; SampleBlock sample = ^{ return a1*b; }; NSLog(@"%f",sample()); a1 = 20; b = 50; NSLog(@"%f",sample());
结果:
2016-08-15 14:43:44.172 命令行工程[1573:107965] 200.0000002016-08-15 14:43:44.175 命令行工程[1573:107965] 200.000000我刚开始以为第二个会输出1000,但是不是。
这是因为变量是局部变量,代码块会在定义时复制并保存它们的状态,所以两次输出结果一样。
6 __block说明符
Blocks可以访问局部变量,但不可以修改。(默认情况下)
#import <Foundation/Foundation.h>typedef int (^MySum)(int, int);int main(int argc, const char * argv[]) { @autoreleasepool { int local = 100; __block int va = 110; MySum sum = ^(int a, int b) { NSLog(@"local = %i,va = %i",local, va); //local++; Variable is not assignable(misssing __block typedef specifier) va++; return a + b +va; }; NSLog(@"调用Sum之前。"); int a = sum(10,10); NSLog(@"调用Sum之后。"); NSLog(@"va = %i",va); NSLog(@"a=%i",a); } return 0;}输出:
2016-02-25 19:23:34.909 命令行工程[1028:136661] 调用Sum之前。2016-02-25 19:23:34.910 命令行工程[1028:136661] local = 100,va = 1102016-02-25 19:23:34.910 命令行工程[1028:136661] 调用Sum之后。2016-02-25 19:23:34.910 命令行工程[1028:136661] va = 1112016-02-25 19:23:34.910 命令行工程[1028:136661] a=131Program ended with exit code: 0由上述例子可以看出局部变量local是不可以在block中改变的,如果修改会警告⚠️:
Variable is not assignable(misssing __block typedef specifier)
而局部变量va是可以修改的,加上__block(两个下划线)。
有些变量无法声明为__block类型的:
不能是长度可变的数组;
不能是包含可变数组的结构体。
NSMutableArray *array = [[NSMutableArray alloc] init];(void)(^blk)(void)= ^{ [array addObject:@""]; //array = [[NSMutableArray alloc] init];<pre name="code" class="objc"><span style="white-space:pre"></span> //Variable is not assignable(misssing __block typedef specifier)};[array addObject:@""]这是没有问题的,而像array赋值则回产生错误。该代码中截获的变量值为NSMUtableArray类的对象,即是截获NSMutableArray类对象用的结构体实例指针。赋值给解惑的自动变量array操作回产生错误,但使用截获的值却不会有任何问题。
将array添加__block说明符就可以改变内容了。
char charAry[] = "test";void (^Sum)(void) = ^{ printf("%c",charAry[0]);//cannot refer to declaration with an array type inside block};上面的代码回报错误,这是因为现在的block,截获自动变量的方法并没有实现C语言数组的截获,所以不可以使用。
char *charAry = "test";void (^Sum)(void) = ^{ printf("%c",charAry[0]);};Sum();通过使用指针就可以读取charAry的内容了,如果想修改,依然需要使用__block。
7 全局变量
将上面的变量改为全局变量会是怎样的结果呢?
static double a1 = 10,b = 20; SampleBlock sample = ^{ return a1*b; }; NSLog(@"%f",sample()); a1 = 20; b = 50; NSLog(@"%f",sample());结果:
2016-08-15 15:00:22.142 命令行工程[1633:113895] 200.0000002016-08-15 15:00:22.142 命令行工程[1633:113895] 1000.000000这说明block定义时不会复制全局变量的值。并且block可以更改全局变量的值。
- Objective-C 14 代码块Block
- Objective-C block(代码块)
- Objective-C - 代码块block
- 【Objective-C】代码块(Block)
- 14,Objective-C语法之代码块(block)的使用
- Objective-C代码块(block)的练习
- Objective-C中的block代码块介绍
- Objective-C代码块Block详解
- Objective-C block (块)
- Objective-C语法之代码块(block)的使用
- Objective-C语法之代码块(block)的使用
- Objective-C语法之代码块(block)的使用
- Objective-C语法之代码块(block)的使用
- Objective-C代码中,块(block)的使用
- Objective-C语法之代码块(block)的使用
- Objective-C语法之代码块(block)的使用
- Objective-C语法之代码块(block)的使用
- Objective-C语法之代码块(block)的使用
- leetcode152-Maximum Product Subarray(乘积最大子数组)
- Java内存泄露的理解与解决
- 文件IO(节点文件)
- 【动态规划】【数位DP】[Codeforces 55 D]Beautiful numbers
- 13.控制器的父子关系
- Objective-C 14 代码块Block
- oc中的类的声明和实现
- 欢迎使用CSDN-markdown编辑器
- HDU 4418 Time travel 概率 高斯
- Schema on Read vs Schema on Write
- POJ3691 DNA repair 题解&代码
- java 选择排序算法
- oc中类和对象
- LVS调度算法(下)——动态调度算法