block 应用及注意事项

一、概述

Block是C级别的语法和运行时特性。Block比较类似C函数,但是Block比之C函数,其灵活性体现在栈内存、堆内存的引用,我们甚至可以将一个Block作为参数传给其他的函数或者Block。

二、热身

先看一个比较简单的Block例子:

int multiplier = 7;

int (^myBlock)(int) = ^(int num) {

return num * multiplier;

};

在这个例子中,myBlock是一个Block变量,它接受一个int类型的参数,返回一个int类型的值。是不是很像C函数?

来,让我们typedef一下

typedef void (^BoolBlock)(BOOL);//一个只接受一个BOOL参数,没有返回值的block

typedef int (^IntBlock)(void);//一个没有参数,返回int的block

typedef BoolBlock (^HugeBlock)(IntBlock);//看看,这个HugeBlock的参数和返回值都是block

三、更详细的例子

注意:上面的typedef都还有效~

主动调用一下:

- (void)someMethod

{

BoolBlock ablock = ^(BOOL bValue) {

NSLog(@"Bool block!");

};

ablock();

}

作为参数返回:

typedef void (^BoolBlock)(BOOL);

- (BoolBlock)foo()

{

BoolBlock ablock = ^(BOOL bValue) {

NSLog(@"Bool block!");

};

return [[ablock copy] autorelease];//一定要copy,将其复制到堆上,更详细的原理,将在后续章节讲解

}

类的一个成员:

@interface OBJ1 : NSObject

@property (nonatomic, copy)BoolBlock block;//理由同上啊,同学们

@end

OBJ1 *obj1 = ...

obj1.block = ^(BOOL bValue) {

NSLog(@"Bool block!");

};

其他函数的参数:

- (void)foo(BoolBlock block)

{

if (block) {

block();

}

}

甚至其他block的参数:

BoolBlock bBlock = ^(BOOL bV){if(Bv){/*do some thing*/}};

HugeBlock hBlock = ^(BoolBlock bB) {bB();};

hBolck(bBlock);

啊,全局变量!:

static int(^maxIntBlock)(int, int) = ^(int a, int b){return a>b?a:b;};

int main()

{

printf("%d\n", maxIntBlock(2,10));

return 0;

}

好了,你知道block大概能怎么用了。

四,特殊的标记,__block

如果要在block内修改block外声明的栈变量,那么一定要对该变量加__block标记:

int main()

{

__block int i = 1024;

BoolBlock bBlock = ^(BOOL bV) {

if (bV) {

i++;//如果没有__block标记,是无法通过编译的。

}

};

}

注意事项:

block可以完全作为delegatge的替代品,而且使用简单,不需要写太多@protocol来定义接口。但使用有以下几点注意。

(1) block不是Object对象,所以对retain无效,要想保留block生命周期,最好通过copy来实现,当然copy后,要记得release。如果不想手动管理,就通过[[[testBlock]
copy] autorelease]来管理。

(2)我们知道一般被block的应用的对象,retainCount会自动加一,为了打破这种 retain circle,可以在对象前加__block,这样block块就不会维护这个对象了。有两种情况

(1)对临时变量的引用如:A  a =[ [[A alloc] init] withBlock:^{

[a action];

[ a release];

}];其实这样会导致内存泄漏,要打破这种circle,只需要在A前面加__block。在我的测试代码中,由于没有对A加__block
导致程序直接崩溃。

__block A  a =[ [[A alloc] init] withBlock:^{

[a action];

[ a release];

}]; 这样A的dealloc方法就会调用

(2)对实例变量的引用如

A  a =[ [[A alloc] init] withBlock:^{

[self action];

}];这样即使调用的self 自身类的release 方法,只要这个block没有执行完,self也不会释放。要打破这种可采用如下做法

__block typeof (self) bself = self; 即通过表达式引用,具体参考typeof用法
,指明 bself 是self类型。

A  a =[ [[A alloc] init] withBlock:^{

[bself action];

}];这样块和self相互独立了。

时间: 2024-10-12 10:36:57

block 应用及注意事项的相关文章

Block使用的注意事项

原文地址:http://jessex.me/?p=181 本文主要是阐述一下Block中如何的使用外部变量以及block本身的内存管理. 先定义一个block变量,作为后续的例子中使用: typedef void(^BlockCC)(void); BlockCC _block; 1.block中引用外部变量 block中可以直接使用外部的变量,比如 int number = 1; _block = ^(){ NSLog(@"number %d", number); }; 那么实际上,在

Delegate/Block/NSNotification与多线程

Delegate/Block/NSNotification是最常用的事件同步方法,各自特点.区别.使用方法就不赘述了. 下面主要想强调一下再多线程中使用Delegate/Block/NSNotification的注意事项. 开发时Delegate的调用方法.Block的调用方法.NSNotification的post方法都可能会在非主线程中调用,此时Delegate/Block/NSNotification的回调方法也将被这个非主线程调用,尤其是Delegate的实现方法很少有人会考虑内部的多线

iOS面试

高德iOS面试整理(顺序有些乱,一面跪了) 1.简单自我介绍 2.聊c语言 3.两个数比较大小不用if和三目运算符 4.int转化为bit数组 5.多态和隐藏 6.const 和define区别 7.String类实现拷贝构造函数注意事项,是否有必要重写 数据结构 1.树层次遍历 2.链表删除 iOS 1.通知和delegate 2.ViewController 生命周期,  手动代码View添加 3.iOS 的click事件的响应过程 4.通知和KVO比较 5.ARC和非ARC (问到静态分析

二十一:jinja2之模板继承

模板继承可以把有共性的一些代码抽出来放到父模板中,其他需要次特性的文件继承模板即可 在jinja2中,使用extends来继承定义好的模板,使用{% block 位置名%} {% endblock %}来预留位置 自己需要定义一个父模板 其他html继承base模板即可拥有所有的模块 block继承的只是位置,默认不继承内容,如果要在指定模块中继承父模板的改模块下的内容,需使用super()方法 调用另一个block中的代码:可以通过{{ self.block名字() }}获取 注意事项 1.子

重要经验五:block作为属性的注意事项

现代ios应用的开发,不使用GCD和block,效率会降低很多,在今年3月份之前,我在block的学习和使用方面,精力和经验都明显不足,在SF有个牛逼同事,不仅自己积累了一套库,而且对这个库持续进行更新和维护,其架构能力和代码水平都不错,他的代码中使用了大量的GCD,为了适应这些技术,我在coding的过程中,开始有意识的多写GCD的代码,刚开始一切顺利,直到我使用block来作为一个对象的属性,这让我纠结了很久. 我遇到的问题是:1,这种属性block,其他类在使用的时候,应该怎么写? 2,b

block注意事项

1.block的声明和注意事项 #import "ZYViewController.h" @interface ZYViewController () @end /*用typedef可以声明一种类型的block*/ //block前加上typedef, 那么就不是一个block指针(变量),而是一种block类型 //给int (^) (int a, int b) 这种block类型 声明了一个别名,叫做Block5 typedef int (^Block5) (int a, int

block使用场景和注意事项

1.使用场景:一般在一个函数的前面和后面都是重复性的东西,只有中间变化,一般使用block 2.注意事项 01:可以访问外面的变量(作用域问题) 02.里外变量同名的时候,访问里面那个(就近原则) 03.可以访问外面的变量,但是不能改外面的值,因为不是同一个地址(只是copy了一份,值传递) 04.想要改变外面变量的值,需要 变量前 加上 _block (地址传递) 05.block类型存放位置:默认是栈,对block进行copy时,放在碓中 在栈中时,访问外面对象,不会对对象 retain一次

关于block使用的5点注意事项

1.在使用block前需要对block指针做判空处理. 不判空直接使用,一旦指针为空直接产生崩溃. if (!self.isOnlyNet) { if (succBlock == NULL) { //后面使用block之前要先做判空处理 return; } id data = [NSKeyedUnarchiver unarchiveObjectWithFile:[self favoriteFile]]; if ([data isKindOfClass:[NSMutableArray class]

ios开发之block的使用,及注意事项

转自:http://my.oschina.net/u/1432769/blog/390401 Block作为C语言的扩展,并不是高新技术,和其他语言的闭包或lambda表达式是一回事.需要注意的是由于Objective-C在iOS中不支持GC机制,使用Block必须自己管理内存,而内存管理正是使用Block坑最多的地方,错误的内存管理 要么导致return cycle内存泄漏要么内存被提前释放导致crash. Block的使用很像函数指针,不过与函数最大的不同是:Block可以访问函数以外.词法