读书人

准确使用Block避免Cycle Retain和Crash

发布时间: 2013-10-15 16:47:37 作者: rapoo

正确使用Block避免Cycle Retain和Crash


Block简介

Block作为C语言的扩展,并不是高新技术,和其他语言的闭包或lambda表达式是一回事。需要注意的是由于Objective-C在iOS中不支持GC机制,使用Block必须自己管理内存,而内存管理正是使用Block坑最多的地方,错误的内存管理 要么导致return cycle内存泄漏要么内存被提前释放导致crash。 Block的使用很像函数指针,不过与函数最大的不同是:Block可以访问函数以外、词法作用域以内的外部变量的值。换句话说,Block不仅 实现函数的功能,还能携带函数的执行环境。

可以这样理解,Block其实包含两个部分内容

  1. Block执行的代码,这是在编译的时候已经生成好的;
  2. 一个包含Block执行时需要的所有外部变量值的数据结构。 Block将使用到的、作用域附近到的变量的值建立一份快照拷贝到栈上。

Block与函数另一个不同是,Block类似ObjC的对象,可以使用自动释放池管理内存(但Block并不完全等同于ObjC对象,后面将详细说明)。

Block基本语法
1234567891011
// 声明一个Block变量long (^sum) (int, int) = nil;// sum是个Block变量,该Block类型有两个int型参数,返回类型是long。// 定义Block并赋给变量sumsum = ^ long (int a, int b) {  return a + b;};// 调用Block:long s = sum(1, 2);

定义一个实例函数,该函数返回Block:

123456789
- (long (^)(int, int)) sumBlock {    int base = 100;    return [[ ^ long (int a, int b) {      return base + a + b;    } copy] autorelease];  }// 调用Block[self sumBlock](1,2);

是不是感觉很怪?为了看的舒服,我们把Block类型typedef一下

123456789
typedef long (^BlkSum)(int, int);- (BlkSum) sumBlock {    int base = 100;    BlkSum blk = ^ long (int a, int b) {      return base + a + b;    }    return [[blk copy] autorelease];}

Block在内存中的位置

根据Block在内存中的位置分为三种类型NSGlobalBlock,NSStackBlock, NSMallocBlock。

读书人网 >网络基础

热点推荐