block知识点回顾
2016-08-04 11:45
232 查看
1、简介
(1)Block是OC中的一种数据类型,在iOS开发中被广泛使用
(2)^是Block的特有标记
(3)Block的实现代码包含在{}之间
(4)大多情况下,以内联inline函数的方式被定义和使用
(5)Block与C语言的函数指针有些相似,但使用起来更加灵活
2、格式说明
(返回类型)(^块名称)(参数类型) = ^(参数列表) {代码实现};
如果没有参数,等号后面参数列表的()可以省略
3、Block可以使用在定义之前声明的局部变量
注意:
(1)在定义Block时,会在Block中建立当前局部变量内容的副本(拷贝)
(2)后续再对该变量的数值进行修改,不会影响Block中的数值
(3)如果需要在block中保持局部变量的数值变化,需要使用__block关键字
(4)使用__block关键字后,同样可以在Block中修改该变量的数值
4、block的常见场景
(1)block的定义形式
小记:Block在定义时并不会执行内部的代码,只有在调用时候才会执行。
举例说明:
结论:执行顺序是1 3 2。这就是最简单的block“回调“,即初始时定义的block代码块中的代码并不会执行,只有当我们主动调用该block时,才会去“回调“最初定义在该block代码块中的代码。
(2)block用作函数的参数时(即Block被当做参数直接传递)
<1> 函数声明中的block的样式如下:
注意:(void (^)(id responseObj))success 中,success是block的变量名,responseObj是block的参数,同时该block无返回值;block用在函数声明中时,和(1)中的block的定义形式很像,对比如下:
<2> 函数调用中的block的样式如下:
注意:和(1)中的block的定义形式对比,相当于将(1)中定义部分中,”=”号之后的部分直接用在了函数调用中。
(3)Block被当做普通参数直接传递
说明:遍历并NSLog() array中的内容,当obj 为”三”时停止遍历
在被当做参数传递时,Block同样可以使用在定义之前声明的局部变量
注意,默认情况下,Block外部的变量,在Block中是只读的!
如果要修改Block之外的局部变量,需要使用__block关键字;
即 ” __block int stopIndex = 1; “
(4)可以使用typedef定义一个Block的类型,便于在后续直接使用
说明:
(1)typedef是关键字,用于定义类型,MyBlock是定义的Block类型;area、sum分别是MyBlock类型的两个Block变量。
(2)尽管,typedef可以简化Block的定义,但在实际开发中并不会频繁使用typedef关键字,这是因为Block具有非常强的灵活性,尤其在以参数传递时,使用Block的目的就是为了立即使用。
官方的数组遍历方法声明如下:
而如果使用typedef,则需要:
而最终的结果却是,除了定义类型之外,EnumerateBlock并没有其他用处。
5、block为什么会实现回调?
(1)block就是一个代码块,但是它的神奇之处在于在内联(inline)执行的时候(这和C++很像)还可以传递参数。同时block本身也可以被作为参数在方法和函数间传递,这就给予了block无限的可能。
(2)block作为参数时,实际上是传递了这个block在内存中的地址。当在另一个类中执行block时,系统会去执行那个内存地址中指向的block。
如果这段block(或者说一段函数)有入参,那么这个时候就把另一个类中的一些值作为参数传递到了block中,作为block的入参。
(3)”回调”的概念,详述如下:
函数Sum(其实是Block)的声明和调用在A类中,而实现部分在B类中。也就是说,B类实现了Sum函数,但并没有权限调用,最终还是由A类触发调用。我们称这样的机制为”回调”。意思是”虽然函数的实现写在B类中,但是真正的调用还是得由A类来完成”。正常函数的声明、实现均在一个类中完成。
(1)Block是OC中的一种数据类型,在iOS开发中被广泛使用
(2)^是Block的特有标记
(3)Block的实现代码包含在{}之间
(4)大多情况下,以内联inline函数的方式被定义和使用
(5)Block与C语言的函数指针有些相似,但使用起来更加灵活
2、格式说明
(返回类型)(^块名称)(参数类型) = ^(参数列表) {代码实现};
如果没有参数,等号后面参数列表的()可以省略
3、Block可以使用在定义之前声明的局部变量
int i = 10; // 当改用__block int i = 10;时,下面的myBlock()将输出100; void(^myBlock)() = ^{ NSLog(@"%d", i); }; i = 100; myBlock(); // 输出10
注意:
(1)在定义Block时,会在Block中建立当前局部变量内容的副本(拷贝)
(2)后续再对该变量的数值进行修改,不会影响Block中的数值
(3)如果需要在block中保持局部变量的数值变化,需要使用__block关键字
(4)使用__block关键字后,同样可以在Block中修改该变量的数值
4、block的常见场景
(1)block的定义形式
void(^demoBlock)() = ^ { NSLog(@"demo Block"); }; // 注意:block代码块中的代码不会主动调用。 int(^sumBlock)(int, int) = ^(int x, int y) { return x + y; };
小记:Block在定义时并不会执行内部的代码,只有在调用时候才会执行。
举例说明:
void (^myBlock)(NSString *str); //1 myBlock = ^(NSString *str) { NSLog(@"---%@", str); //2 }; myBlock(@"11111"); //3
结论:执行顺序是1 3 2。这就是最简单的block“回调“,即初始时定义的block代码块中的代码并不会执行,只有当我们主动调用该block时,才会去“回调“最初定义在该block代码块中的代码。
(2)block用作函数的参数时(即Block被当做参数直接传递)
<1> 函数声明中的block的样式如下:
+ (void)get:(NSString *)url params:(NSDictionary *)params success:(void (^)(id responseObj))success failure:(void (^)(NSError *error))failure;
注意:(void (^)(id responseObj))success 中,success是block的变量名,responseObj是block的参数,同时该block无返回值;block用在函数声明中时,和(1)中的block的定义形式很像,对比如下:
(1)中的定义形式为: void(^demoBlock)() int(^sumBlock)(int, int) 如果用在函数声明中,应改为如下形式: void(^)()demoBlock // 可简化为 void(^)demoBlock int(^)(int, int)sumBlock
<2> 函数调用中的block的样式如下:
[XBHttpTool post:@"https://www.baidu.com" params:params success:^(id responseObj) { // 做一些特定的事情 } failure:^(NSError *error) { // 做一些特定的事情 }];
注意:和(1)中的block的定义形式对比,相当于将(1)中定义部分中,”=”号之后的部分直接用在了函数调用中。
(3)Block被当做普通参数直接传递
NSArray *array = @[@"一", @"二", @"三", @"四"]; [array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { NSLog(@"第 %d 项内容是 %@", (int)idx, obj); if ([@"三" isEqualToString:obj]) { *stop = YES; } }];
说明:遍历并NSLog() array中的内容,当obj 为”三”时停止遍历
在被当做参数传递时,Block同样可以使用在定义之前声明的局部变量
int stopIndex = 1; NSArray *array = @[@"一", @"二", @"三", @"四"]; [array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { NSLog(@"第 %d 项内容是 %@", (int)idx, obj); if ([@"三" isEqualToString:obj] || idx == stopIndex) { *stop = YES; } }];
注意,默认情况下,Block外部的变量,在Block中是只读的!
如果要修改Block之外的局部变量,需要使用__block关键字;
即 ” __block int stopIndex = 1; “
(4)可以使用typedef定义一个Block的类型,便于在后续直接使用
typedef double(^MyBlock)(double, double); MyBlock area = ^(double x, double y) { return x * y; }; MyBlock sum = ^(double a, double b) { return a + b; }; NSLog(@"%.2f", area(10.0, 20.0)); NSLog(@"%.2f", sum(10.0, 20.0));
说明:
(1)typedef是关键字,用于定义类型,MyBlock是定义的Block类型;area、sum分别是MyBlock类型的两个Block变量。
(2)尽管,typedef可以简化Block的定义,但在实际开发中并不会频繁使用typedef关键字,这是因为Block具有非常强的灵活性,尤其在以参数传递时,使用Block的目的就是为了立即使用。
官方的数组遍历方法声明如下:
- (void)enumerateObjectsUsingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop))block; // 其中block是参数名称,(^)即此时不需要指定block的名称。
而如果使用typedef,则需要:
typedef void(^EnumerateBlock)(id obj, NSUInteger idx, BOOL *stop); - (void)enumerateObjectsUsingBlock:(EnumerateBlock)block;
而最终的结果却是,除了定义类型之外,EnumerateBlock并没有其他用处。
5、block为什么会实现回调?
(1)block就是一个代码块,但是它的神奇之处在于在内联(inline)执行的时候(这和C++很像)还可以传递参数。同时block本身也可以被作为参数在方法和函数间传递,这就给予了block无限的可能。
(2)block作为参数时,实际上是传递了这个block在内存中的地址。当在另一个类中执行block时,系统会去执行那个内存地址中指向的block。
如果这段block(或者说一段函数)有入参,那么这个时候就把另一个类中的一些值作为参数传递到了block中,作为block的入参。
(3)”回调”的概念,详述如下:
函数Sum(其实是Block)的声明和调用在A类中,而实现部分在B类中。也就是说,B类实现了Sum函数,但并没有权限调用,最终还是由A类触发调用。我们称这样的机制为”回调”。意思是”虽然函数的实现写在B类中,但是真正的调用还是得由A类来完成”。正常函数的声明、实现均在一个类中完成。
相关文章推荐
- Objc-C 知识点回顾 七 block
- C语言一些知识点回顾
- C语言知识点回顾
- Block知识点总结
- C语言重要知识点回顾
- Android视频学习(九):内容提供者和知识点回顾
- c++知识点回顾
- 数据库的学习和之前不熟悉的知识点回顾
- J2SE知识点回顾(上)
- Android群英传知识点回顾——第十三章:Android实例提高
- UI- UIView控件知识点回顾
- Flask知识点回顾以及重点内容
- muduo 6 网络库学习之BlockinngQueue<T>类、ThreadPool 类、Singleton类封装中的知识点
- JAVA基础知识点回顾
- Es6知识点回顾
- 一、php知识点回顾总结
- 课后知识点回顾十 集合2
- block简单回顾
- 面试前的准备---C#知识点回顾----05
- 那些不能遗忘的知识点回顾——操作系统系列(笔试面试高频题)