博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Block使用的注意事项
阅读量:4616 次
发布时间:2019-06-09

本文共 2048 字,大约阅读时间需要 6 分钟。

原文地址:

本文主要是阐述一下Block中如何的使用外部变量以及block本身的内存管理。

先定义一个block变量,作为后续的例子中使用:

typedef void(^BlockCC)(void);BlockCC _block;

 

 

1、block中引用外部变量

block中可以直接使用外部的变量,比如

 

int number = 1;_block = ^(){    NSLog(@"number %d", number);};

 

那么实际上,在block生成的时候,是会把number当做是常量变量编码到block当中。可以看到,以下的代码,block中的number值是不会发生变化的:

 

int number = 1;_block = ^(){    NSLog(@"number %d", number);};number = 2;_block();

 

则输出的值为 1,而不是2。原因就是如上所说。

如果要在block中尝试改变外部变量的值,则会报错的。对于这个问题的解决办法是引入__block标识符。将需要在block内部修改的变量标识为__block scope。更改后的代码如下:

 

__block int number = 1;_block = ^(){    number++;    NSLog(@"number %d", number);};

 

而这个时候,其实block外部的number和block内部的number指向了同一个值,回到刚才的在外部改变block的例子,它的输出结果将是2,而不是1。有兴趣的可以自己写一个例子试试。

 

 

2、block自身的内存管理

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

我在view did load中创建了一个block:

 

- (void)viewDidLoad{    [superviewDidLoad];    int number = 1;    _block = ^(){    NSLog(@"number %d", number);};}

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

 

 

- (IBAction)testDidClick:(id)sender {    _block();}

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

修改代码如下:

 

_block = ^(){    NSLog(@"number %d", number);};_block = [_blockcopy];

 

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

[array addObject:[[^{    NSLog(@"hello!");} copy] autorelease]];

 

3、循环引用

这一点其实是在第一点的一个小的衍生。当在block内部使用成员变量的时候,比如

 

@interface ViewController : UIViewController{    NSString *_string;}@end

 

在block创建中:

_block = ^(){    NSLog(@"string %@", _string);};

 

这里的_string相当于是self->_string;那么block是会对内部的对象进行一次retain。也就是说,self会被retain一次。当self释放的时候,需要block释放后才会对self进行释放,但是block的释放又需要等self的dealloc中才会释放。如此一来变形成了循环引用,导致内存泄露。

修改方案是新建一个__block scope的局部变量,并把self赋值给它,而在block内部则使用这个局部变量来进行取值。因为__block标记的变量是不会被自动retain的。

 

__block ViewController *controller = self;_block = ^(){    NSLog(@"string %@", controller->_string);};

先写到这里,基本是我在用block时候碰到的一些问题。需要更详细的解释,可以看看《Adanced Mac OS X Programming》这本书,推荐给大家

转载于:https://www.cnblogs.com/huihuige/p/5794137.html

你可能感兴趣的文章
分享21个超棒的单页面网站设计
查看>>
Java Native Interface Specification Contents 翻译
查看>>
随笔⑥ 关于线程 --- 线程操作的主要方法
查看>>
转:解开Android应用程序组件Activity的”singleTask”之谜
查看>>
Virtex6 GTX设计总结:预加重、均衡、输出振幅的值
查看>>
fork和exec函数
查看>>
fs/ext2/inode.c相关函数注释
查看>>
HTTP无状态协议详解
查看>>
nodejs mongodb 查询要看的文章
查看>>
codeforces 622B B. The Time
查看>>
个人日报0628
查看>>
BeanDefinition的Resource定位——2
查看>>
实验九
查看>>
回文词
查看>>
Hibernate之Query.uniqueResult()结果为数值的注意事项
查看>>
学习记事
查看>>
java 子类重写父类的方法应注意的问题
查看>>
[LevelDB] LevelDB理论基础
查看>>
如果部署Excel 加载项?
查看>>
【codecombat】 试玩全攻略 第一关kithguard地牢
查看>>