block简介
ios4.0系统已开始支持block,在编程过程中,blocks被Obj-C看成是对象,它封装了一段代码,这段代码可以在任何时候执行。Blocks可以作为函数参数或者函数的返回值,而其本身又可以带输入参数或返回值。它和传统的函数指针很类似,但是有区别:blocks是inline的,并且它对局部变量是只读的。
下面是理论部分:
1、block的定义
|
1
2
3
4
5
6
7
8
9
10
11
12
|
1 // 声明和实现写在一起,就像变量的声明实现 int a = 10; 2 int (^aBlock)(int, int) = ^(int num1, int num2) { 3 4 return num1 * num2; 5 6 }; 7 // 声明和实现分开,就像变量先声明后实现 int a;a = 10; 8 int (^cBlock)(int,int); 9 cBlock = ^(int num1,int num2)10 {11 return num1 * num2;12 }; |
其中,定义了一个名字为aBlock的blocks对象,并携带了相关信息:
1、aBlock 有两个形式参数,分别为int类型;
2、aBlock 的返回值为int 类型;
3、等式右边就是blocks的具体实现;
4、^ 带边blocks声明和实现的标示(关键字);
当然,你可以定义其他形式的block。e.g:无返回值,无形式参数等;
|
1
2
3
4
5
|
1 void (^bBlock)() = ^()2 {3 int a = 10;4 printf(num = %d,a);5 }; |
2、blocks 访问权限
blocks可以访问局部变量,但是不能修改。
|
1
2
3
4
5
6
|
1 int a = 10;2 int (^dBlock)(int) = ^(int num)3 {4 a++;//not work!5 return num * a;6 }; |
此处不能修改的原因是在编译期间确定的,编译器编译的时候把a的值复制到block作为一个新变量(假设是a‘ = 10),此时a'和a是没有关系的。
这个地方就是函数中的值传递。如果要修改就要加关键字:__block或者static
|
1
2
3
4
5
6
|
1 __block int a = 7;2 int (^dBlock)(int) = ^(int num)3 {4 a++;// work!5 return num * a;6 }; |
3、block的调用
block调用就像调用函数一样。e.g:
| 1 | int c = aBlock(10,10); |
4、block 应用
假设我们熟悉代理递值的话,对代理我们可能又爱有恨!我们先建立模型A页面 push B页面,如果把A页面的值传递到B页面,属性和单例传值可以搞定!但是如果Pop过程中把B页面的值传递到A页面,那就可以用单例或者代理了!说到代理,我们要先声明协议,创建代理,很是麻烦。常常我们传递一个数值需要在两个页面间写很多代码,这些代码改变页面的整体顺序,可读性也打了折扣。所以,此时,block是一种优化方案!
5、 block的内存管理
block本身是像对象一样可以retain,和release。但是,block在创建的时候,它的内存是分配在栈(stack)上,而不是在堆(heap)上。他本身的作于域是属于创建时候的作用域,一旦在创建时候的作用域外面调用block将导致程序崩溃。比如下面的例子。 我在view did load中创建了一个block:
- - (void)viewDidLoad
- {
- [superviewDidLoad];
- int number = 1;
- _block = ^(){
- NSLog(@number %d, number);
- };
- }
并且在一个按钮的事件中调用了这个block:
- - (IBAction)testDidClick:(id)sender {
- _block();
- }
此时我按了按钮之后就会导致程序崩溃,解决这个问题的方法就是在创建完block的时候需要调用copy的方法。copy会把block从栈上移动到堆上,那么就可以在其他地方使用这个block了~ 修改代码如下:
- _block = ^(){
- NSLog(@number %d, number);
- };
- _block = [_blockcopy];
同理,特别需要注意的地方就是在把block放到集合类当中去的时候,如果直接把生成的block放入到集合类中,是无法在其他地方使用block,必须要对block进行copy。不过代码看上去相对奇怪一些:
- [array addObject:[[^{
- NSLog(@hello!);
- } copy] autorelease]];
6、循环引用
对于非ARC下, 为了防止循环引用, 我们使用__block来修饰在Block中使用的对象:
对于ARC下, 为了防止循环引用, 我们使用__weak来修饰在Block中使用的对象。原理就是:ARC中,Block中如果引用了__strong修饰符的自动变量,则相当于Block对该变量的引用计数+1。
这一点其实是在第一点的一个小的衍生。当在block内部使用成员变量的时候,比如
|
1
|
|
- @interface ViewController : UIViewController
- {
- NSString *_string;
- }
- @end
在block创建中:
- _block = ^(){
- NSLog(@string %@, _string);
- };
这里的_string相当于是self->_string;那么block是会对内部的对象进行一次retain。也就是说,self会被retain一次。当self释放的时候,需要block释放后才会对self进行释放,但是block的释放又需要等self的dealloc中才会释放。如此一来变形成了循环引用,导致内存泄露。
修改方案是新建一个__block scope的局部变量,并把self赋值给它,而在block内部则使用这个局部变量来进行取值。因为__block标记的变量是不会被自动retain的。
|
1
|
|
- __block ViewController *controller = self;
- _block = ^(){
- NSLog(@string %@, controller->_string);
- };
block简介的更多相关文章
- iOS Block简介
Block是对象,它封装了一段代码,这段代码可以在任何时候执行.block可以作为函数参数或者函数的返回值,而其本身又可以带输入参数或返回值.它和传统的函数指针很类似,但是有区别:block是inli ...
- iOS中block简介-作用域
转:http://www.2cto.com/kf/201401/269467.html 用block可以定义任意的代码片段,将其像对象一样传入另一个方法:它是c级别的语法,和C语言中的函数指针非常相似 ...
- 代码块(block)简介
代码块是对C语言中函数的扩展,由C语言实现,所以在以C为基础的语言内都是有效的,包括Objective_C,C++和Objective-C++,在Xcode的GCG与Clang工具中是有效的,但这不属 ...
- iOS Block界面反向传值
在上篇博客 <iOS Block简介> 中,侧重解析了 iOS Block的概念等,本文将侧重于它们在开发中的应用. Block是iOS4.0+ 和Mac OS X 10.6+ 引进的对C ...
- block使用小结、在arc中使用block、如何防止循环引用
引言 使用block已经有一段时间了,感觉自己了解的还行,但是几天前看到CocoaChina上一个关于block的小测试主题: [小测试]你真的知道blocks在Objective-C中是怎么工作的吗 ...
- 浅谈 block(1) – clang 改写后的 block 结构
这几天为了巩固知识,从 iOS 的各个知识点开始学习,希望自己对每一个知识理解的更加深入的了解.这次来分享一下 block 的学习笔记. block 简介 block 被当做扩展特性而被加入 GCC ...
- iOS中Block的基础用法
本文简介 本章不会对Block做过多的实现研究.只是讲解基本的用法.纯粹基础知识.结合实际项目怎么去做举例.Block使用场景,可以在两个界面的传值,也可以对代码封装作为参数的传递等.用过GCD就知道 ...
- Block 的基本用法
iOS中Block的基础用法 转载自简书 本文简介 本章不会对Block做过多的实现研究.只是讲解基本的用法.纯粹基础知识.结合实际项目怎么去做举例.Block使用场景,可以在两个界面的传值,也可以对 ...
- 【转】正确使用Block避免Cycle Retain和Crash
原文地址:http://tanqisen.github.io/blog/2013/04/19/gcd-block-cycle-retain/ 使用指南:http://blog.csdn.net/nic ...
随机推荐
- C# 空字典遍历
Data.instance.boolMap 是一个字典. 若Data.instance.boolMap == null 的话,遍历的时候,就会报错: 若Data.instance.boolMap = ...
- Django orm查询操作
基于双下划线查询切记!!!!正向查询按字段,反向查询按表名的小写 正向:在Book表里设置关联Obj表,Book------>Obj就是正向查询 反向:在Book表里设置关联Obj表,Obj-- ...
- (转)AIX 5.3安装SSH .
AIX 5.3安装SSH . 原文:http://blog.csdn.net/chunhua_love/article/details/12004845 环境:OS:AIX 5.3SSH: opens ...
- (转) IP子网划分
原文:http://blog.csdn.net/birdie_l/article/details/77994610 子网划分公式计算法 实例一 实例二 心算思路总结: B类公式算法举例: 总结:此表 ...
- SmartRF Flash Programmer突然打不开显示界面的办法【亲测有效】
在尝试打开任务管理器结束任务之后重新打开依然无果,在尝试了SmartRF Flash Programmer卸载重装无数次之后依然无果的况状,我被SmartRF Flash Programmer存在界面 ...
- js循环里进行回调,引用循环里的变量,发现只是最后值的问题
做项目的时候,栽在一个小地方,是这样的 我有很多个坐标点,我想把这些坐标点都绑定一个事件,当点击了这个坐标点之后,发送一个ajax 请求,将坐标点的id 发出去,等待显示返回的数据 但是实际当中,无论 ...
- 06-spring常见的连接池配置
1 准备工作 首先,我们准备jdbc属性文件 database.properties,用于保存连接数据库的信息,利于我们在配置文件中使用. 只要在applicationContext.xml(Spri ...
- Python并发编程之进程池与线程池
一.进程池与线程池 python标准模块concurrent.futures(并发未来) 1.concurrent.futures模块是用来创建并行的任务,提供了更高级别的接口,为了异步执行调用 2. ...
- Spring文件上传Demo
package com.smbea.controller; import java.io.File; import java.io.FileOutputStream; import java.io.I ...
- php socket简单使用
php的socket编程算是比较难以理解的东西吧,不过,我们只要理解socket几个函数之间的关系,以及它们所扮演的角色,那么理解起来应该不是很难了,在笔者看来,socket编程,其实就是建立一个网络 ...