简介

block 类似标准的c函数,除了一些函数体一些可执行的代码,还可以把变量绑定到自动栈或者托管堆上.....和js里的闭包、c# lambda表达式有些类似,实质是一个函数指针。与函数指针的区别在于其可以捕获(capture)其定义时作用域内的变量。

Block objects are a C-level syntactic and runtime feature. They are similar to standard C functions, but in addition to executable code they may also contain variable bindings to automatic (stack) or managed (heap) memory. A block can therefore maintain a set of state (data) that it can use to impact behavior when executed.
 
格式  :  (返回值)(^Name)(参数列表)
void(^Test)(void)=^{ printf("%s","hello world!"); };
在Objective-C语言中,一共有3种类型的block(可通过isa指针打印查看):
1._NSConcreteGlobalBlock 全局的静态block,不会访问任何外部变量。
2._NSConcreteStackBlock 保存在栈中的block,当函数返回时会被销毁。
3._NSConcreteMallocBlock 保存在堆中的block,当引用计数为0时会被销毁。
需要注意的是ARC下,没有栈block,尝试打印block对象,的确没有看到MallocBlock,但是通过clang反编译看到isa还是指向的_NSConcreteStackBlock。

结构

一个block其实是一个对象,有他自己的属性,结构如下

  • isa指针,所有对象都有该指针,用于实现消息传递等功能(ias一般指向父类、元类)
  • flags,用于按bit位表示一些block的附加信息
  • reserved,保留变量。
  • invoke,函数指针,指向具体的block实现的函数调用地址。
  • descriptor, 表示该block的附加描述信息,主要是size大小,以及copy和dispose函数的指针。
  • variables,capture过来的变量,block能够访问它外部的局部变量,就是因为将这些变量(或变量的地址)复制到了结构体中。

变量

block支持全局变量、静态变量、全局的函数、局部变量、封闭的参数,而且支持两种其他变量的类型__block修饰符(读写)、只读。

引用官方文档:

Within the block object’s body of code, variables may be treated in five different ways.

You can reference three standard types of variable, just as you would from a function:

  • Global variables, including static locals
  • Global functions (which aren’t technically variables)
  • Local variables and parameters from an enclosing scope

Blocks also support two other types of variable:

  1. At function level are __block variables. These are mutable within the block (and the enclosing scope) and are preserved if any referencing block is copied to the heap.
  2. const imports.

block变量使用规则:

  1. 全局变量,包括静态变量可以直接在block使用(block内可以直接修改,注意内存,会有强引用)
  2. block参数传递,类似函数参数
  3. 存在栈上的变量(非静态的),即局部变量。这些变量将会被截获,他们将会被block引用,他们的值是在初始block之前截获最近的一次
  4. 定义在封闭区间的本地变量(局部变量),用__block修饰符,是可以修改的,任何的更改将会反应到封闭的区间,包括任何引用到的block
  5. block内部定义的变量,和函数内部定义的变量一样。

引用官方文档:

The following rules apply to variables used within a block:

  1. Global variables are accessible, including static variables that exist within the enclosing lexical scope.
  2. Parameters passed to the block are accessible (just like parameters to a function).
  3. Stack (non-static) variables local to the enclosing lexical scope are captured as const variables.Their values are taken at the point of the block expression within the program. In nested blocks, the value is captured from the nearest enclosing scope. 
  4. Variables local to the enclosing lexical scope declared with the __block storage modifier are provided by reference and so are mutable.Any changes are reflected in the enclosing lexical scope, including any other blocks defined within the same enclosing lexical scope. These are discussed in more detail in “The __block Storage Type.” 
  5. Local variables declared within the lexical scope of the block, which behave exactly like local variables in a function. Each invocation of the block provides a new copy of that variable. These variables can in turn be used as const or by-reference variables in blocks enclosed within the block.

后续会详细介绍block的各种变量使用。

block 解析 - 简介的更多相关文章

  1. iOS开发之网络数据解析(二)--XML解析简介

    前言:本篇随笔介绍的是XML解析. 正文: 1.XML解析方式有2两种: DOM:一次性将整个XML数据加载进内存进行解析,比较适合解析小文件 SAX:从根元素开始,按顺序一个元素一个元素往下解析,比 ...

  2. Block解析(iOS)

    1. 操作系统中的栈和堆 我们先来看看一个由C/C++/OBJC编译的程序占用内存分布的结构: 栈区(stack):由系统自动分配,一般存放函数参数值.局部变量的值等.由编译器自动创建与释放.其操作方 ...

  3. iOS开发之网络数据解析(一)--JSON解析简介

    前言:对服务器请求之后,返回给客户端的数据,一般都是JSON格式或者XML格式(文件下载除外) 本篇随便先讲解JSON解析. 正文: 关于JSON: JSON是一种轻量级的数据格式,一般用于数据交互 ...

  4. block 解析 - 内存

    block结构体相应的也有一个成员引用,这样会增加对局部变量的 _para1引用,在Block销毁的时候引用就释放掉了 我们了解到了用__block修饰的变量,可以在block内部修改,__block ...

  5. block 解析 - 成员变量

    回顾 在 上一篇 中我们讲了截获变量特性,对于局部变量,变量不加__block修饰符,在block内部是无法修改变量的值.而且 对值类型的修改,如果block初始化后,无法同步到block内部 对于指 ...

  6. block 解析 - 局部变量

    局部变量 block内使用局部变量,一般都是截获变量(只读),截获离block初始化最近的一次的值. 引用官方文档: Stack (non-static) variables local to the ...

  7. block 解析 - 形参变量

    block形参 之前漏了一篇block形参的介绍,这里给补上. block形参就是定义block带的参数,和函数的参数使用一样,我们可以在block随意使用修改block形参. 我们来看个例子: 我们 ...

  8. block 解析 - block变量

    block变量 上一篇 讲的是block静态变量的特性,这里我们来看一下_block变量.引用官方: You can specify that an imported variable be muta ...

  9. block 解析 - 静态变量

    静态变量 上一篇 我们了解了block全局变量的使用,静态变量和全局变量一样,可以直接在block内部使用,也可以在block内部修改 引用官方文档: Global variables are acc ...

随机推荐

  1. HDU 1104 Remainder( BFS(广度优先搜索))

    Remainder Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Sub ...

  2. ExtJs 4 的filefield上传后 返回值success接受不正常

    问题解决了,我修改了返回类型为setContentType("text/html")可以正确解析了,感到很奇怪,其他的地方使用setContentType("applic ...

  3. 访问Tableau自带的PostgreSQL数据库

    突然发现公司Tableau服务器的数据库大小急剧增加,因此决定直接连上数据库排查.过程记录如下:最后发现有个http_requests 表体积巨大(7G),本来以为是数据缓存什么的.结果是日志问题o( ...

  4. 融合python2和python3

    很多情况下你可能会想要开发一个程序能同时在python2和python3中运行. 想象一下你开发了一个模块,成百上千的人都在使用它,但不是所有的用户都同时使用python 2和3.这种情况下你有两个选 ...

  5. 【原】Spring和Dubbo整合案例和过程

    Dubbo是Alibaba开源的分布式服务框架,它最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解耦合(或者最大限度地松耦合).从服务模型的角度来看,Dubbo采用的是一种非常简单的模 ...

  6. 字符串分割函数Demo

    #include <stdio.h> int getLength(char *string); int main(int argc, char **argv){ char str[12] ...

  7. 子进程管理模块subprocess

    subprocess模块允许你生成子进程,连接管道,并获取返回的代码. 一.使用subprocess模块 模块中定义了一个Popen类:       subprocess.Popen(args, bu ...

  8. BZOJ 1607: [Usaco2008 Dec]Patting Heads 轻拍牛头

    1607: [Usaco2008 Dec]Patting Heads 轻拍牛头 Description   今天是贝茜的生日,为了庆祝自己的生日,贝茜邀你来玩一个游戏.     贝茜让N(1≤N≤10 ...

  9. poj 1200 Crazy Search(hash)

    题目链接:http://poj.org/problem?id=1200 思路分析:从数据来看,该题目使用线性时间算法,可见子串的比较是不可能的:使用hash可以在常数时间内查找,可以常数时间内判重, ...

  10. Tilemill + tilestream + mapbox.js 自制地图

    感谢Mapbox,带来了一整套完整的地图方案. 你可以把你的地图放在Mapbox的网站上.也可以使用他们提供的开源软件自己架设地图服务. Mapbox的地图方案包括web,ios和android. 不 ...