ios Block详细用法
ios4.0系统已开始支持block,在编程过程中,blocks被Obj-C看成是对象,它封装了一段代码,这段代码可以在任何时候执行。Blocks可以作为函数参数或者函数的返回值,而其本身又可以带输入参数或返回值。它和传统的函数指针很类似,但是有区别:blocks是inline的,并且它对局部变量是只读的。

下面是理论部分:

  1、block的定义

 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         void (^bBlock)() = ^()
2 {
3 int a = 10;
4 printf(num = %d,a);
5 };

  2、blocks 访问权限

  blocks可以访问局部变量,但是不能修改。

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         __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);
  bBlock();

  4、block 应用

  假设我们熟悉代理递值的话,对代理我们可能又爱有恨!我们先建立模型A页面 push B页面,如果把A页面的值传递到B页面,属性和单例传值可以搞定!但是如果Pop过程中把B页面的值传递到A页面,那就可以用单例或者代理了!说到代理,我们要先声明协议,创建代理,很是麻烦。常常我们传递一个数值需要在两个页面间写很多代码,这些代码改变页面的整体顺序,可读性也打了折扣。所以,此时,block是一种优化方案!

5、 block的内存管理

block本身是像对象一样可以retain,和release。但是,block在创建的时候,它的内存是分配在栈(stack)上,而不是在堆(heap)上。他本身的作于域是属于创建时候的作用域,一旦在创建时候的作用域外面调用block将导致程序崩溃。比如下面的例子。 我在view did load中创建了一个block:


  1. - (void)viewDidLoad
  2. {
  3. [superviewDidLoad];
  4. int number = 1;
  5. _block = ^(){
  6. NSLog(@number %d, number);
  7. };
  8. }

并且在一个按钮的事件中调用了这个block:


  1. - (IBAction)testDidClick:(id)sender {
  2. _block();
  3. }

此时我按了按钮之后就会导致程序崩溃,解决这个问题的方法就是在创建完block的时候需要调用copy的方法。copy会把block从栈上移动到堆上,那么就可以在其他地方使用这个block了~ 修改代码如下:


  1. _block = ^(){
  2. NSLog(@number %d, number);
  3. };
  4. _block = [_blockcopy];

同理,特别需要注意的地方就是在把block放到集合类当中去的时候,如果直接把生成的block放入到集合类中,是无法在其他地方使用block,必须要对block进行copy。不过代码看上去相对奇怪一些:


  1. [array addObject:[[^{
  2. NSLog(@hello!);
  3. } copy] autorelease]];

6、循环引用
对于非ARC下, 为了防止循环引用, 我们使用__block来修饰在Block中使用的对象:
对于ARC下, 为了防止循环引用, 我们使用__weak来修饰在Block中使用的对象。原理就是:ARC中,Block中如果引用了__strong修饰符的自动变量,则相当于Block对该变量的引用计数+1。
这一点其实是在第一点的一个小的衍生。当在block内部使用成员变量的时候,比如


  1. @interface ViewController : UIViewController
  2. {
  3. NSString *_string;
  4. }
  5. @end

在block创建中:


  1. _block = ^(){
  2. NSLog(@string %@, _string);
  3. };

这里的_string相当于是self->_string;那么block是会对内部的对象进行一次retain。也就是说,self会被retain一次。当self释放的时候,需要block释放后才会对self进行释放,但是block的释放又需要等self的dealloc中才会释放。如此一来变形成了循环引用,导致内存泄露。
修改方案是新建一个__block scope的局部变量,并把self赋值给它,而在block内部则使用这个局部变量来进行取值。因为__block标记的变量是不会被自动retain的。


  1. __block ViewController *controller = self;
  2. _block = ^(){
  3. NSLog(@string %@, controller->_string);
  4. };

ios Block详细用法的更多相关文章

  1. IOS开发Block详细用法

    Block简介:       ios4.0系统已开始支持block,在编程过程中,blocks被Obj-C看成是对象,它封装了一段代码,这段代码可以在任何时候执行.Blocks可以作为函数参数或者函数 ...

  2. iOS block的用法

    本章学习目标: 1. 了解何谓block. 2. 了解block的使用方法. Block 是iOS在4.0之后新增的程式语法,严格来说block的概念并不算是基础程式设计的范围,对初学者来说也不是很容 ...

  3. iOS block的用法 by -- 周傅琦君

    X.1 初探Block X.1.1 宣告和使用Block 我们使用「^」运算子来宣告一个block变数,而且在block的定义最后面要加上「;」来表示一个完整的述句(也就是将整个block定义视为前面 ...

  4. iOS Block详细介绍(block实现)

    Block的实现 数据结构定义 block的数据结构定义如下图 对应的结构体定义如下: struct Block_descriptor { unsigned long int reserved; un ...

  5. iOS中block的用法 以及和函数用法的区别

    ios中block的用法和函数的用法大致相同 但是block的用法的灵活性更高: 不带参数的block: void ^(MyBlock)() = ^{}; 调用的时候  MyBlock(); 带参数的 ...

  6. iOS开发:使用Block在两个界面之间传值(Block高级用法:Block传值)

    iOS开发:使用Block在两个界面之间传值(Block高级用法:Block传值)   使用Block的地方很多,其中传值只是其中的一小部分,下面介绍Block在两个界面之间的传值: 先说一下思想: ...

  7. IOS NSUserDefaults 讲解 用法

    IOS NSUserDefaults 讲解 用法    NSUserDefaults适合存储轻量级的本地数据,比如要保存一个登陆界面的数据,用户名.密码之类的,个人觉得使用NSUserDefaults ...

  8. css基础之 font的简写规则 以及 自定义 CSS3 @font-face详细用法

    Part 1 font简写 CSS的命名规则是用英文字母 数字 和下划线(一般用小写)来命名.简写css font的好处有三:一是写起来方便(就像键盘快捷键):二是简化代码:三是帮助你熟悉和深刻理解c ...

  9. iOS block 机制

    本文要将block的以下机制,并配合具体代码详细描述: block 与 外部变量 block 的存储域:栈块.堆块.全局块 定义 块与函数类似,只不过是直接定义在另一个函数里,和定义它的那个函数共享同 ...

随机推荐

  1. jquery ajaxFileUpload异步上传文件

    ajaxFileUpload.js 很多同名的,因为做出来一个很容易. 我用的是这个:https://github.com/carlcarl/AjaxFileUpload 下载地址在这里:http:/ ...

  2. jasperreports+iReport+jatoolsPrinter制作报表笔记

    此文章是基于 EasyUI+Knockout实现经典表单的查看.编辑 一. 准备工作 1. 点击此下载相关的文件,并把 ims 文件夹放到 ims 工程对应的路劲下 2. 参考网址:杰创打印控件 二. ...

  3. flask_sqlalchemy filter 和filter_by的区别

    1. filter需要通过类名.属性名的方式,类名.属性名==值.filter_by 直接使用属性名=值,可以看源码filter_by需要传一个 **kwargs 2. filter支持> &l ...

  4. 从官网下载mod_jk.so

    最近在搞apache和tomcat集群,这里就要用到mol_jk.so,在官网找了很久才知道在哪里下载,英语是硬伤啊. 1.打开tomcat官网 http://tomcat.apache.org/ 2 ...

  5. maven更改仓库地址

    安装maven后,maven的默认的仓库地址在  C:\Users\Administrator\.m2\repository 修改maven的仓库地址的步骤是,1.在某个盘符下建立一个文件夹,当做现在 ...

  6. node定时任务

    var schedule = require('node-schedule') require('shelljs/global'); function scheduleCronstyle(){ sch ...

  7. 怎样修改织梦网站的favicon图标

    现在很多的网站浏览器栏上都有favicon图标,比如百度,大家用织梦做好网站后,可能发现自己的网站favicon图标默认的不好看,如何修改织梦网站的favicon导航图标呢,很多人肯定有过困惑,小编遇 ...

  8. CentOS 7运维管理笔记(12)----GUI配置工具Webmin的安装

    早期的Linux系统管理员或是Web管理员在修改服务器配置时使用最多的就是vi编辑器,但是现在越来越多的基于GUI界面的配置工具出现了,毕竟人们还是喜欢以直接的可视化的方式来修改服务器的配置,而不是再 ...

  9. Android学习——BroadCast(二)

    这篇博文介绍有序广播的使用 有序广播的发送 和普通广播完全相同,只需要更换发送的方式即可 ordered.setOnClickListener(new View.OnClickListener() { ...

  10. 初级游戏外挂编程详解 windows运行原理+游戏辅助编程 游戏外挂编程

    详解游戏辅助编程 [目录] 1-什么是Windows API 2-Windows进程 3-Windows 的内存的运行原理 4-windows 中句柄的概念 5-Windows的变量类型 6-辅助实现 ...