一、block是什么?

block是带有自动变量(局部变量)的匿名函数。它是C语言的扩展功能,C语言标准并不支持block。

block是Objective-C的闭包实现,正如C++中的Lambda表达式。闭包简单理解即函数中的函数,闭包在JavaScript中是一个很重要的概念。作为“函数中的函数”,block跟函数很类似。

1、block变量 VS 函数指针变量

return_type (^block_name) (parameter list) // ^标识block,参数名可省略
int (^blk) (int, int) = ^(int a, int b) {
return a+b;
}; // 创建一个匿名block,并赋值给一个名为blk的block变量 int ret = blk(, ); // block调用
return_type (*fptr_name) (parameter list) // 函数指针,参数名可省略
int f(int a, int b) {
return a+b;
} // 函数定义
int (*fptr)(int, int); // 函数指针声明 fptr = f; // 函数名f其实就是个指针 int ret = fptr(, ); // 通过函数指针调用函数

通常的变量定义语句是像下面这样的,但是block变量的语法形式比较难记:

变量类型 变量名 = 变量值;

为此,可以用typedef给block变量类型起个简单的别名

typedef int (^blk) (int, int); // 相比正常的block变量声明,只是前面多了typedef,blk就变成了这种block变量类型的别名。

blk sumBlk = ^(int a, int b) {
return a+b;
}; // 这样就回到熟悉的变量定义语句格式了  

2、block也是一种对象,根据它在内存中的位置,分为全局block、栈block和堆block。可以通过NSLog打印识别具体是哪一种block对象。

1)没引用外部变量的是全局block

int a = ;
void (^blk) () = ^{
//NSLog(@"%d", a);
};
NSLog(@"%@", blk); // <__NSGlobalBlock__: 0x102d23be0>

2)引用了外部变量,在MRC下是栈block,可以通过[block copy]把栈block拷贝到堆上,转成堆block;在ARC下,很多时候系统帮我们完成了拷贝,具体什么时候,要实测。

int a = ;
void (^blk) () = ^{
NSLog(@"%d", a);
};
NSLog(@"%@", blk); // ARC下 <__NSMallocBlock__: 0x60400005ba50>
// MRC下 <__NSStackBlock__: 0x7ffeefbff518>

3)栈block,类似局部变量,出了它的作用域,会被系统回收内存,再调用可能导致程序崩溃。

4)堆block,正如其他Objective-C对象那样,利用引用计数进行内存管理。

3、在block里面,默认不能修改外部变量。这里指的是不能修改变量本身,如果是指针类型,它指向的内容是可以修改的。

局部变量

全局变量

静态变量

__block变量

成员变量

属性

- (void)testBlock {
int i = 10;
NSLog(@"[%p] [%d]", &i, i);
void (^blk)() = ^(){
NSLog(@"[%p] [%d]", &i, i);
i++; // 不能修改,报错:Variable is not assignable (missing __block type specifier)
};
blk();
} 输出:
[0x60800044e810] [10]
[0x60800044e810] [10]
- (void)testBlock {
NSMutableString *str = [[NSMutableString alloc] initWithString:@"abc"];
NSLog(@"[%p] [%@]", str, str);
void (^blk)() = ^(){
NSLog(@"[%p] [%@]", str, str);
[str appendString:@"def"]; // 可以修改指针指向的内容
str = [[NSMutableString alloc] initWithString:@"another str"]; // 不能修改指针本身,报错:Variable is not assignable (missing __block type specifier)
};
blk();
NSLog(@"[%p] [%@]", str, str);
} 输出:
[0x60000025df10] [abc]
[0x60000025df10] [abc]
[0x60000025df10] [abcdef]

  

  

  

struct Block_descriptor {
unsigned long int reserved;
unsigned long int size;
void (*copy)(void *dst, void *src);
void (*dispose)(void *);
}; struct Block_layout {
void *isa;
int flags;
int reserved;
void (*invoke)(void *, ...);
struct Block_descriptor *descriptor;
/* Imported variables. */
};

5、循环引用

1)原因:对象A有block属性,即持有block;而block中又用了对象A,使得block也持有了对象A。

self.blk = ^{
[self method];
};

2)

__weak typeof(self) weakSelf = self;
self.blk = ^{
__strong typeof(weakSelf) strongSelf = weakSelf;
[self method];
};

block不会捕获形参到内部持有

block也是对象

自动型,托管型,变量绑定

========================================================

循环引用

成员变量

持有对象的成员变量即间接持有对象。

__block修饰符可以用来避免循环引用?block不会持有__block对象。

__block修饰符在MRC和ARC下区别很大?

Objective-C block深入理解的更多相关文章

  1. 对于block的理解,block的面试题

    1.block跟swift中的闭包(closure)基本一样,都常用于值的回调,特别是在多线程的网络请求回调中,使用起来极为方便. 2.block的开头是"^",接着是由小括号所报 ...

  2. Objective C block背后的黑魔法

    前言 block在Objective C开发中应用非常广泛,我们知道block会捕获外部对象,也知道使用block要防止循环引用. "知其然而不知其所以然"是一件非常痛苦的事情,那 ...

  3. Block 朴实理解

    转载自:http://www.cnblogs.com/lzz900201/archive/2013/04/17/3025340.html block是个什么玩意儿 Block是Apple Inc.为C ...

  4. inode和block的理解

    什么是inode和block? 所谓的inode就是索引节点(index node)的意思,在每一个存储设备被格式化创建文件系统后,所有的文件大致被分为了两部分,分别是inode和block. 其中i ...

  5. Block使用

    1.对block的理解 >  block是iOS4.0之后出现的,是仿照java中匿名函数所创造的,它是c级别的语法,效率比协议-代理高 >  block的是一个匿名函数(没有名字的函数) ...

  6. iOS-重回block小白之路

    在我刚刚接触iOS开发的时候,是通过MJ老师讲的OC基础入门的,iOS圈的人应该基本都知道MJ大神吧,即便如此大神,讲解完block之后我依然感觉晕晕乎乎的,直到后来真正进公司做项目,依然感觉这是自己 ...

  7. Swift 05.Block

    Swift的函数用法还真是灵活.但是个人感觉更灵活的还是闭包. swift闭包的概念大抵相当于OC的block的概念.如果对于block的理解很透彻的话,闭包的原理性的东西还是很好理解的. 剩下的就是 ...

  8. block(代码块)的介绍以及使用方法和变量之间的关系

    http://blog.csdn.net/menxu_work/article/details/8762848 block(代码块)的介绍以及使用方法和变量之间的关系 block(代码块)的介绍以及使 ...

  9. Objective-C之Block

    Block基本概念 本小节知识点: [了解]什么是Block [理解]block的格式 1.什么是Block Block是iOS中一种比较特殊的数据类型 Block是苹果官方特别推荐使用的数据类型, ...

随机推荐

  1. web print

    <!doctype html> <html lang="en"> <head> <meta charset="utf-8&quo ...

  2. 2018-02-18 Antlr4实现简单语言之条件语句

    本系列之前的文章: Antlr4的分析错误处理 Antlr4实现数学四则运算 Antlr4添加中文变量赋求值,括号,各种问题 Antlr4: 修改语法规则更接近普通BNF格式 Antlr4实现简单语言 ...

  3. 【20190129】CSS-定位问题记录

    很多情况下我在写div的时候都不会把高度写死,而是用子元素撑开高度的方式,但是如果子元素设置了浮动或者position绝对定位,就相当于把子元素从文档流中拿出来了,这时父元素的高度就不能被子元素撑开了 ...

  4. docker-使用Dockerfile制作镜像

    最近项目中有使用docker,组内做了关于docker的培训,然后自己跟着研究了一下,大概了解如何使用.我是基于tomcat镜像制作(不需要安装jdk,配置环境变量),基于centos镜像制作需要安装 ...

  5. 安卓开发_startActivityForResult的详细用法

    一个需求:一个activity到另一个activity进行一些设置,返回第一个activity的时候 获取第二个activity设置的数据 百度了一下,发现startActivityForResult ...

  6. dubbo-admin管理控制台的安装部署(最简单)

    Dubbo-admin最简单的安装部署,十分钟就能搞定! 网上找的安装教程虽说详细,但是就是因为详细操作起来而显得繁琐.今天,我帮大家跳过这些繁琐的步骤,简单快捷的安装部署dubbo-admin. 1 ...

  7. linux 下的ssh

    ssh服务 1.检查是否有被安装,命令 rpm -qa|grep "ssh" 2.检查ssh有没有在运行,命令 rpm -qa|grep "ssh" 3.如何启 ...

  8. element-ui的回调函数Events的用法

    做轮播的时候想用这个change回调函数,但是官方文档上竟然就只列了这么一行东西,完全没有示例代码(也可能我没找到哈) 鼓捣了半天,东拼西凑终于找到了靠谱的使用方法,其实很简单 在轮播组件上加上@ch ...

  9. Asp.net Mvc身份验证

    1.安装组件 Microsoft.AspNet.Identity.Core,身份认证核心组件 安装Microsoft.AspNet.Identity.EntityFramework,EF实现身份认证 ...

  10. Scrapy爬取遇到的一点点问题

    学了大概一个月Scrapy,自己写了些东东,遇到很多问题,这几天心情也不大好,小媳妇人也不舒服,休假了,自己研究了很久,有些眉目了 利用scrapy 框架爬取慕课网的一些信息 步骤一:新建项目 scr ...