美文网首页iOS专攻
你想了解的Block,都告诉你

你想了解的Block,都告诉你

作者: han_zero | 来源:发表于2019-08-28 14:01 被阅读0次

Block

block的本质 -- -- OC对象

block最终都是继承自NSBlock类型,而NSBlock继承于NSObjcet。那么block其中的isa指针其实是来自NSObject中的。这也更加印证了block的本质其实就是OC对象

block的捕获机制

局部变量:
会被block捕获到内部
auto类型的是值传递,内部不能修改值
static是指针传递,可以修改值。

全局变量:
不会被捕获到block内部
可以修改值

Q:为什么局部变量需要捕获?
考虑作用域的问题,需要跨函数访问,就需要捕获
<style>
td
{
text-align:center;
}
</style>

<table border="1" bgcolor="#778899" class="td">
<tr>
<th colspan="2">变量类型</th>
<th>捕获到block内部</th>
<th>访问方式</th>
</tr>
<tr>
<td rowspan="2">局部变量</td>
<td>auto</td>
<td>√️</td>
<td>值传递</td>
</tr>
<tr>
<td>static</td>
<td>√</td>
<td>地址传递</td>
</tr>
<tr>
<td colspan="2">全局变量</td>
<td>×</td>
<td>直接访问</td>
</tr>
</table>

(html代码转义失败了,直接看截图吧😅)


image.png

block有哪几种类型

  • _NSConcreteStackBlock:
    只用到外部局部变量、成员属性变量,且没有强指针引用的block都是StackBlock。
    StackBlock的生命周期由系统控制的,一旦返回之后,就被系统销毁了。
  • _NSConcreteMallocBlock:
    有强指针引用或copy修饰的成员属性引用的block会被复制一份到堆中成为MallocBlock,没有强指针引用即销毁,生命周期由程序员控制
  • _NSConcreteGlobalBlock:
    没有用到外界变量或只用到全局变量、静态变量的block为_NSConcreteGlobalBlock,生命周期从创建到应用程序结束

ARC环境下,一旦Block赋值就会触发copy,__block就会copy到堆上,Block也是__NSMallocBlock。ARC环境下也是存在__NSStackBlock的时候,这种情况下,__block就在栈上。
MRC环境下,只有copy,__block才会被复制到堆上,否则,__block一直都在栈上,block也只是__NSStackBlock,这个时候__forwarding指针就只指向自己了。

在MRC环境下,__block根本不会对指针所指向的对象执行copy操作,而只是把指针进行的复制。
而在ARC环境下,对于声明为__block的外部对象,在block内部会进行retain,以至于在block环境内能安全的引用外部对象,所以才会产生循环引用的问题!

<pre>
int age = 1;
void (^block1)(void) = ^{
NSLog(@"block1");
};

void (^block2)(void) = ^{
NSLog(@"block2:%d",age);
};

NSLog(@"%@/%@/%@",[block1 class],[block2 class],[^{
NSLog(@"block3:%d",age);
} class]);
</pre>

堆block

1.如果block被拷贝到堆上:

  • 会调用block内部的copy函数
  • copy函数内部会调用_Block_object_assign函数
  • _Block_object_assign函数会根据auto变量的修饰符 (__strong、__weak、__unsafe_unretained)做出相应的操作,形成强引用(retain)或者弱引用

2.如果block从堆上移除

  • 会调用block内部的dispose函数
  • dispose函数内部会调用_Block_object_dispose函数
  • _Block_object_dispose函数会自动释放引用的auto变量(release)

Q:当block内部访问了对象类型的auto变量时,是否会强引用?

  • 如果block在栈空间,不管外部变量是强引用还是弱引用,block都会弱引用访问对象
  • 如果block在堆空间,如果外部强引用,block内部也是强引用;如果外部弱引用,block内部也是弱引用

解决堆block的循环引用办法:

  • 释放block
  • 在block里不要强引用对象

masonry解决的办法是释放block

- (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *))block {
    self.translatesAutoresizingMaskIntoConstraints = NO;
    MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self];
    block(constraintMaker);
    return [constraintMaker install];
}

看as_makeConstraints的方法实现会发现设置布局的方法中的block对象并没有被View所引用,block(constraintMaker)而是直接在方法内部同步执行,执行完以后block将释放,其中捕捉的外部变量的引用计数也将还原到之前。这个block只是个栈block,栈block有个特性就是它执行完毕之后就出栈,出栈了就会被释放掉,构不成循环引用。

__weak typeof(person) weakPerson = person;
__unsafe_unretained Person *person = [[Person alloc] init];
__block Person *person = [[Person alloc] init];

__weak:不会产生强引用,指向的对象销毁时,会自动让指针置为nil
__unsafe_unretained:不会产生强引用,不安全,指向的对象销毁时,指针存储的地址值不变
__block:必须把引用对象置为nil,并且要调用该block

weakSelf 是为了block不持有self,避免Retain Circle循环引用。在 Block 内如果需要访问 self 的方法、变量,建议使用 weakSelf。strongSelf的目的是因为一旦进入block执行,假设不允许self在这个执行过程中释放,就需要加入strongSelf。block执行完后这个strongSelf 会自动释放,没有不会存在循环引用问题。如果在 Block 内需要多次 访问 self,则需要使用 strongSelf。
strongSelf实质是一个局部变量(在block这个“函数”里面的局部变量),当block执行完毕就会释放自动变量strongSelf,不会对self进行一直进行强引用。

相关文章

  • 你想了解的Block,都告诉你

    Block block的本质 -- -- OC对象 block最终都是继承自NSBlock类型,而NSBlock继...

  • block底层那些你不知道的事

    如果block只掌握了怎么去应用,那了解了block的皮毛。若想要精通block,非得了解block的本质不行! ...

  • 重拾我的英语学习

    很多鸡汤都告诉你:“你想要的,岁月都会给你”。但是它没告诉你:“你想要的,岁月凭什么白白给你”!所有的逆袭,都是努...

  • 12月31日反思

    你的各种行为都是谁告诉你的?每种行为背后都一定有个受益人。你得到了什么?是你想要的吗?还是别人告诉你的,那就是你想...

  • 【读书清单】安心才是喜乐

    作者:寂静 001了解谁 当你想看透别人时,请告诉自己了解全世界不如了解你自己。 空虚:指我们的心里没有东西,是心...

  • block(一)了解block

    block就是代码块组成的匿名函数,block是oc对于闭包的实现 1.可以嵌套定义,定义block方法和定义函数...

  • 解梦:回到老家,叔叔在小卖部门口骗我

    文/白茶心 梦就像抓不住的精灵,如果你不了解它,它就给你躲猫猫,如果你了解它,它就乖乖的告诉你你想要的信息, 1....

  • 探秘ios中block的循环引用问题

    hello,小伙伴们!ios中自从引入了block,代理就在慢慢淡出我们的视野,那么block的使用大家都了解吗?...

  • 我为何喜欢不放假的工作

    喜欢现在的工作。 一、自由。领导告诉你负责哪些工作,你想做快点,慢点,你想开工早点,晚点,都随意,只要司机来了,你...

  • [iOS]Block技术中的weak-strong

    本篇文章的主要内容 了解何谓block。 了解block的使用方法。Block 是iOS在4.0版本之后新增的程序...

网友评论

    本文标题:你想了解的Block,都告诉你

    本文链接:https://www.haomeiwen.com/subject/blipectx.html