美文网首页@IT·互联网
关于block的理解

关于block的理解

作者: fantasy028 | 来源:发表于2018-01-25 15:38 被阅读0次

block的类型详解

关于block的知识,在网络上的资料那是相当的多。不过这里还是想来谈谈自己对block的理解。本文不会深入到重写成C风格代码来理解,但也不会简单到仅仅是告诉你怎么用。

本文着眼点于从内存管理的角度来理解block。既然是从内存管理的角度来理解,那么我们就先来说一下Objc中block有哪几种类型吧。

在Objc中block被分为三种类型:

1. NSGlobalBlock——全局区,分布在数据段(.data)

2. NSStackBlock——分布在栈(stack)区域

3. NSMallocBlock——分布在堆(heap)区域

现在我们已经知道了block分为三种类型,不过需要注意的是在ARC情况下,其实已经基本不会有NSStackBlock这种block类型被分配了(这里说基本不会,至于为什么会这么说,详细会在关于属性修饰的部分谈)。纠其原因因该和内存自动管理的技术实现复杂度有关吧(个人猜测不做理论深入)。到这一步,我们接下来应该来,需要了解的就是这三种类型分别在什么样的情况下才会被分配。

总体来讲,我们需要遵循的原则就是:

1. 当block中引用了全局变量的时候,会被分配到NSGlobalBlock中

2. 当block没有引用任何block之外的变量的时候会分配到NSGlobalBlock中

对于上面这两点该怎么理解呢?这里强调一下,上述两点是并不是说同时满足。而是满足其中之一。也就是说,无论我们的block无论在什么地方被定义,只要block引用来全局变量或者block中没有引用block之外的变量就会被分配到NSGlobalBlock中。

这事个什么原则呢?当然,这个与生命周期有关了,对于全局变量的生命周期自不必说。对与没有引用block之外的变量怎么理解呢?这个当然还是与生命周期有关。我们知道在一个函数内定义的变量或者一个对象中的变量或属性其生命周期与函数或对象的生命周期是一致的,一旦他们被释放之后,如果block继续占用这些变量那么必将导致内存泄漏。而对与没有引用block之外的变量的block其外部变量的存在性并不影响block本身的运行,而只与block代码本身的存在性有关。

在了解了这些之后,我们还要来区分一下NSStackBlock与NSMallocBlock。NSStackBlock在ARC机制下是不存在的,这一点前面已经提到了,也就是说,在ARC机制下,所有除了分配成NSGlobalBlock之外的block都属于NSMallocBlock之列。

接下来,我们就来谈谈在MRC下的使用吧。在MRC下,除了上述情况之的block之外的block默认为NSStackBlock类型。这就决定了其生命周期与创建环境本身的生命周期相关。但是,在使用过程中,很多时候,其定义与使用并不在同一个地方,也就是说其创建环境的生命周期可能不能够保障其在调用的时候还继续延续着,那么我们该怎么办呢?对这个问题,我们要先要明确的是栈(stack)区域的内容属于自动分配的,由系统自动管理,既然如此,我们要想控制其生命周期的话,我们自然应该将分配管理权限从系统管理变为我们自己管理。而这个过程就需要我们将其copy到堆(heap)区域。这个过程,Objc提供了两个专门的函数Block_copy(...)和Block_release(...)。对于这两个方法的具体用法网上资料比较多就不细说了。

block作为属性传递

不过最后还有一点,就是block作为对象的属性传递问题。我们知道,对象的属性修饰符包括,weak,strong,retain,copy,assign。那么,在用这些修饰符时是怎样一个存在呢?其实,如果对block属性赋值,那么属性的block的类型与传入的block类型相同。

strong, retain, copy

strong,retain,copy三个属性修饰符,strong,retain属于计数+1操作。copy为复制操作。对用这三个修饰符修饰的属性赋值,最终block的类型为:存在外部参数引用的情况下分配为NSMallocBlock,不存在外部引用的情况下将分配为NSGlobalBlock。

weak,assign

对于weak,assign修饰符修饰block属性,weak目前仅在ARC条件下可用,而assign则均可用。不过,这里要注意的是,在直接对这两种类型传入一个定义好的block,和直接对block设置时把block定义本身作为值传入时,确是有所不同的。

这里举个例子吧,定义了一个TestBlock类。

接下来在使用的过程我们使用如下代码:

首先,我们可以看一下MRC下的的block类型分配如下图信息:

接着,对同样的代码在来观察一下ARC下的效果分配的block类型,如下:

到此,我们注意到,在MRC下和ARC下对内存分配类型的处理差别在于对block属性赋值时,MRC对block的内存分配策略采取的与前面讲到的MRC情况下的内存分配是一致的。差别在于,ARC下的分配策略,直接对多想属性为block的属性传入的数据为block定义,且block引用了外部变量(非全局变量)时,这个属性指向的block为NSStackBlock。这也就是为什么前面在谈Block类型时没有对ARC的类型为NSGlobalBlock和NSMallocBlock做绝对的定论。

那么,为什么会存在这样一个结局呢?个人根据经验理解(具体原因自己慢慢探索吧),这个原因就在与block的作用域以及修饰符的作用域本身上了。对于直接把block的定义赋值给block性质的属性是,block的作用域和定义它的函数本身并没太大的关系,它的上下文环境在某种程度上已经脱离了函数的上下问环境,但是由于属性本身亦是若引用,不对block做所在区域的处理。

相关文章

  • 关于block的理解

    FBI WARNING:纯属个人见解,有可能是错误的理解。O(∩_∩)Oblock作用1.可以传递数据,取代代理模...

  • 关于block的理解

    block的类型详解 关于block的知识,在网络上的资料那是相当的多。不过这里还是想来谈谈自己对block的理解...

  • 关于Block的理解

    Block是将函数及其执行上下文封装起来的对象。在开发过程中我们经常会用到Block处理一些事物,下面我们就对Bl...

  • 九、Block之(一)Block内部结构及调用本质

    一、Block内部数据结构 1.调用分析 2.关于block调用中 block->FunPrt()的理解 bloc...

  • 关于 __ block 再理解

    关于 __ block 再理解 我们都知道:block不准修改外部变量的值,这里所说的外部变量的值,指的是栈中指针...

  • 关于IOS的Block的理解

    IOS中的Block大致分为三种 第一种 堆block 我们知道 程序在内存中 堆是程序员分配的和使用的栈是系统使...

  • iOS 关于block前缀的理解

    关于block:修饰符 用copy(要从堆区 拷贝到栈区) 前缀修饰符: __block:默认情况下,bloc...

  • Block原理探究(上篇)-Block本质及存储域问题

    主要内容:1.理解Block的本质2.理解Block的存储域分类3.理解Block的Copy原理 一、探究Bloc...

  • Block

    将我认为的比较易懂的关于block的文章整理到一起: 文章链接: 你真的理解__block修饰符的原理么? __b...

  • iOS面试之Block大全

    Block Block内容如下: 关于Block 截获变量 __block修饰符 Block的内存管理 Block...

网友评论

    本文标题:关于block的理解

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