00:07
好,欢迎大家来到罗教育公开课,那么我是今天讲课老师T,那么今天我们主要讲一下这个lo,那么首先我们先来看一下啊,我们今天这节课要讲的一个内容。那么第一点就是什么呢?第一点就是我们block的一个追战探究,因为大家之前如果听过我的课的话,我对block追战这一块是特别特别在意的,并且什么呢?这一块为什么我特别在意,因为就是因为在面试的时候,那么现在大厂那么经常会去把block与堆战联系在一起,为什么要联系在一起,因为堆栈是你普通一个程序员,Is程序员,那么对你的一个技能深入,那么最好的一个印证。那么第二点什么呢?哎,我们block原理,那么这个底层原理就是block,它底层是一个结构体,包括它的一个耗原理到底是怎么样的,我们知道block是能耗的嘛,然后呢,第三点就是我们重点去学习block的一个三种类型,明白什么场景下会触发BLOCK1拷贝,这个非常重要,这个是面试中经常问到的一个点。
01:06
那么第四点就是捕捞和循环油产生的原因,以及怎么来解决,这个是个非常经典的一个问题,那么今天哎,咱们主要针对于为什么以及怎么来解决,然后呢,第四点就是咱们的面试题,那么这个面试题我们主要看一下第1.lo类型与内存相关一个面试题。那么正好契合我们第一个,然后第二个就是我们block能捕获变量,那么战胜的block也能吗?哎,这个是不是很经典一个问题,然后呢,第三个咱们战block与block使用上有什么区别,怎么去判断block一个类型,然后呢,我们再来看最后一个。那么使用copy修饰的堆上的block是一定是对上了block吗?那么如何去触发block的拷贝?然后呢,对战到底有什么区别是吧,这都是非常非常经典的一个面题,然后呢,杠杠未课怎么来解决循环移动,那么这就是咱们今天课程一个主要内容,感兴趣的同学我们来扣波六六好吧。
02:02
那么首先第一点我们先打开今天的第一份代码,我们来到这个block的源码里面,来到block源码里面,那么首先第一点我们看到这个慢点M在这个地方我写了几句代码,那么这个代码我们简单来解读一下,上面是我通过is是不是定义了一个self这么一个对象。我在这个地方能不能这么直接定义self这个对象?有没有问题,这样定义没有问题吧,为什么?因为我当前是不是在一个函数里面,这个self并没有其他的一些特殊含义吧,所以我这么写是没有问题的吧。对不对。然后呢,第二个哎呀这句话,这句代码我们先不管,然后呢,我们主要看什么呢。主要看下面,那么首先第一点,我在这个地方获取了我们当前self的一个,那么来到这个block内部,我又获取了这个,请问现在。我执行这个慢函数,那么里面会输出我self的return,那么输出几呢?来,大家给我一个答案。
03:07
现在这就是面试题,大家给我一个答案。这局is那会输出几?这一局NS会输出几?上面这个地方,哎,是不是有同学说是一,那么下面这一句呢。下面不输出,哎,非常好,这位社会主义接班人非常好,为什么不输出,因为我没有调用吧,对吧,那下面我调用了之后,那么请问这里面会输出几。这里面会输出几。来大家看一下。小眼睛说,三还有其他同学。来,大家给我一点,给我一点反应,非常非常重要啊。因为从这个题我就能看出大家对block的一个理解。好,这位社会主义接班人也说是一个一,那么我们直接来运行这个代码,来看一下到底会输出。
04:02
哎,直接来报错,报什么错。哦。等一下啊,我把这个代码先注册掉。好,慢点。大家来运行啊,好,现在building在走。来,我们来。看到这边。然后把这个清空掉。还没有打印出来啊,还没有打印出来。好,把这个断点也注射掉,注射掉之后回来,那么我们可以看到是不是现在它输出了几啊,是不是在这个地方它输出一个一,在这个地方输出一个三吧,对不对,那么我们可以看到一个变量被block捕获了之后,是不是经过了两次拷贝啊。是两次强引用啊,那么这个两次两次。两次到底发生在什么地方?那么接下来什么呢?我现在来捕获这个week,那么请问现在应该会输出几?
05:00
Self。我现在前面变成了一个杠杠未修饰的这个week self现在会输出解。上面已经输出一下面这个地方会输出几。燕宁说,一、还有没有其他同学?大家快点,我把这个题过了,我给大家讲这个原理好不好?好,我现在卡的加直接来运行。大家发现没有,是不是在这个地方输出了一个二?好,那么现在就有一个问题了,那为什么我直接引用self会是输出一,然后呢,我引用week self会输出一个二呢?那么首先第一点,那么我们要从不lock的一个底层原理开始给大家讲起,那么我们打开第二个代码。那么在第二个代码里面呢,我们首先要明白一点。那么block为什么它有一个count?因为block在我们OC中是不是作为一个对象存在的,这个没有问题吧,没有问题的同学给我扣个一,是不是作为一个对象存在的?
06:00
所以说我是不是可以直接通过block去调用我们的一个方法,为什么调用。因为我们block里面,它作为对象,它是不是也有A指针啊,那么它有ISA指针,我们知道在我们OC中,是不是所有的对象的ISA最后都是指向。它的一个NS,那么所以它可以直接干什么,是不是调用这个copy。好,那么大家看到这个block,大家看到这个block。水腾抗的你没有看到是吧?没关系,咱们一会儿再来讲,好吧,先给大家提起这个意思来,哎,告诉大家,那么哎,你们可能平常对这个东西有忽略,那么现在我问一下大家。我现在直接调用了copy之后,那么这个copy之后的block是一个什么类型的block?我们知道block是不是有老放在全局的lo,有麦lo。
07:02
也有我们那个放在战区的block,那么现在我拷贝了之后,这个copy block是一个什么类型的block?堆区是吧,还有没有其他同学,你们都说堆区吗?没有之前听过看了老师课的同学吗?这个是堆去的block吗?都是堆去吗?哎呀,那就好办了呀,百分号艾特来copy。啊,大家今天一定要好好跟着我听课啊。来,我直接扛加下来运行在这个地方打一个断点。大家今天咱们回答除了全局去block的同学,今天一定要跟着我好好来听课啊。来大家稍等一下啊,一定要你们这是一个什么类型的。行,大家稍微等一下啊,这个模拟器有点慢。我我发现,因为好几个同学我比较眼熟,应该之前是听过我的课的同学来我们看一下啊,看一下这copy block来NS不。
08:02
然后IC这是什么类型的block个block吧,好,那么现在就一个问题,那为什么我明明调用了copy,是我调用了copy和我在这个地方用copy修饰一个block,是不是其实是一个意思啊。那么也就印证了什么呢?是不是我的block内部没有使用任何的外部变量,或者我们的局部变量,它应该是我们的一个lolo,那么所以我把这个地方注释掉,删掉之后我CF的一个do work,那么这个类型的block。好,Copy来修饰。正常的block一样,那么请问这个self的do work,它是一个什么类型的block?我们举一反三一下。大家大胆的来回答一下,按照刚才我们的一个印证。全局,全局还有没有其他同学?咱们136位同学,哎,全局去葡萄,哎非常好是吧。你们大家一定要什么呢?哎,大胆的去回答这个问题,来,我点击这个地方,然后我们直接跳到self do work来copy是不是格globallo,好,那么在这个地方,那么有同学就有疑问了,那么怎么去判断block的类型呢?
09:12
在这个地方,我给大家总结出了一个三个判断条件,那么位于我们全局区的一个block block,那么就是在block内部不使用外部变量,或者只使用静态变量和全局变量,就是我们的一个global block。你明白没有,所以说咱们一会儿你们先把这三条规则来记住,我们一会儿去实践一下,到底是不是这样的好不好。然后呢,位于堆区的是什么呢?在block内部使用局部变量或者OC属性,并且复制给强引用或者copy来修饰。那么我们看到这个self的,它是不是只满足堆区的这两个条件的后一个吧?他是不是不满足前面这一个吧。所以说我们现在干一个事情,如果说我定一个in a等于零。
10:01
然后呢,我在这里面使用一下这个局部变量,那么现在这个block应该变成一个什么类型的block,全局区block存在哪一会我来讲好吧。现在应该是一个什么类型的卡?是不是对啊,哎,你们先按照我这个条件先来判断,先来判断,然后呢,判断的对不对,我们来打印一下,看一下好不好。我直接他们家来运行。好,来点击。来到这里是不是变成了malo克了,那么说明什么呢?说明我的这个判断条件是不是对的,哎,在block内部使用局部变量或者OC的属性,并且负这个强应用或者靠来修是它是不是应该是堆区的,那么战区的跟我们堆上的是不是正好相反,相反的点在哪?是不是战区的block,它内部。不能复制给强引用或者copy来修饰,对不对?好,这位同学说,为啥呢?那么我们首先来探索一下不lock的一个底层原理,那么这一点我们平常在做开发的时候都知道,Block底层是一个什么?
11:06
是不是一个结构体?你们先把问题抛出来,我一个一个给大家来讲,好吧,结构体。是不block底层是一个结构体,那么它这个底层的结构体是一个什么形式呢?那么我在这个地方给大家来看一下它的结构体是一个什么形式,那么我打再打开这个block的源码。打开这个源码之后呢,我来到这个地方,我看一下这里面有没有这个脚本啊。有没有这个脚本。哦,好像是没有这个脚本,我说为什么会报错呢?然后呢,我把这个脚本我从我的VIP课程里面我来拷贝一下,好吧,大家稍微等我一下。这个脚本。好,这个脚本我把它拷贝一下,拷贝一下放到今天的公开课block代码,咱们的一个block源码最下面,那么最下面之后呢,在这里面,那么同时我去启用。使用这个脚本来到这个地方,来到这个beauty pass,把它来打开好,那么这个脚本是干什么动呢?那么这个脚本就是可以使你在你的project里面去写相应的咱们的一个C语句,然后呢,可以直接来执行,那么我们知道我们平常写的是不是直接在这里面去执行相关的需要,或者执行相关的脚本吧。
12:21
那么我们现在可以通过一个文件直接在这里面写,那么这样有什么好处呢?我们知道我们平常执行的是要它的一个输出结果,他输出在哪,是不是你每次标定里面的这些信息吧。这个里面你去找你执行脚本的信息还是比较乱的吧,对不对。所以说我想到了一种方式,利用脚本的方式,把我们每次执行脚本输出的结果重定位到我们终端上,所以我来到这个地方,我获取一下当前终端的一个标识符。哎,通输入TT,那么拿到这个标识符之后呢,我来到这个地方把它来配置一下,诶正好也是配置上了。
13:02
那么接下来我们来看一下这个命令。那么push我们的s RC root block text,我们知道s RC root是不是代表当前项目的这个源码路径啊?也就是什么呢,是不是代表这个路径啊。对不对,对的话给我扣一是不root是不是代表这个路径啊。然后这个block text是不是实际上就是进入到这个目录里面。那么进入到这个目录里面之后呢,我们再往后看,哎,我们执行一个咱们的一个叉C,把我们的点M文件转化成我们的一个C加加文件,最后呢,再从再打开这个文件,最后再从当前的目录里面,哎,走掉,那我来看一下整个脚本配置的有没有错误。啊,我们的s RC root block插库的run。啊,应该问题不大,问题不大之后我直接卡加来拼一下。
14:03
直接那么大家看到没有,是不是现在直接按照我的命令把这个转化后的C加加打开,打开了,并且我们来到终端,你看到没有,我们刚才执行脚本的这个语句是不是也放到这个地方了。然后呢,并且里面执行命令,他给我们报的警告是不是也放到这个终端上面了。那么是不是比我们平常在这个building里面去找。这个输出信息要清楚的多了吧,对不对,大家觉得对不对,这个脚本还是非常非常有用的嘛,对吧。那么大家想不想要这个脚本?想不想要这个脚本,想要的话给我扣个一。想要的话,那么我今天把这个脚本作为资料提供给大家好不好?那么我把这个脚本现在看到,哎,我把它拷贝一下,放到今天的这个资料里面,那么与此同时,咱们今天还给大家提供了另外几份资料,那么第一份资料呢,是run lo timer,那么这个timer是讲什么呢?就是讲平常是不是你面试的时候老问这个run timer为什么不准,那么我在这里面做了一个详细的对比。
15:14
帮助你去理解哎,Timer为什么它不准,为什么它精度不高,它的底层原理是什么?那么给大家呃,做成一个项目放到这里面,大家会呃回去可以来看一下,那么再一个是什么呢?啊,编译命令,那么刚才我们说的那个叉c wrong的那个命令是我没有告诉大家,哎,里面具体一些细节,那么大家可以拿到这个文档,那么大家看到这个地方。可烂里面,哎,这些常用的参数到底是干什么的,那么这个地方配合着什么来使用呢?我们来了这个。平常你是不是编译的时候会报错,那报错的时候,你比方说是不是在这个地方,它显示的编译我们点M,哎编译我们点M的时候,它实际上是用什么呢?是不是用我们的,哎这个杠X指定它的编译语言,哎杠T这些参数到底是什么意思,你拿到我这个资料在里面来搜索好不好?
16:06
这里面非常非常全,并且我给大家举了非常非常多的例子,并且呢,哎,包括我们的dsm文件怎么查看是吧,我们怎么去查看我们的ma o,包括呢,静态库怎么去解压缩,怎么去链接,怎么去生成,怎么去查看符号表,是不是我们链接器,包括怎么去链接,哎,怎么去按重排,需要哪些命令都在这个文件里面。这是给大家提供了第二份资料。那么还有一份资料是什么呢?一个可编译的OPPOGC781的源码,这个主要是一会儿我们来看这个杠杠可原理的时候。要告诉大家,然后呢,最后一个什么呢?咱们今天用到了补lo的源码,那么所以说今天一共给大家提供这么五份资料,非常非常的详细,那么有需要的同学哎,咱们今天接下来听这个课,不要错过,看的老师也是为数不多的把这个脚本提供给大家,这里面我都是注释的非常非常详细的。给大家这个哎,五秒钟的时间来添加一下好不好,关掉之后,那么我们来到这里面,那么我们看到刚才生成的这个C加加,C加加,那么首先我们卡曼的加下键找到我们当前这个慢函数,那么这个慢函数大家看到没有,是不是我通过nslo in实际上干了什么事情,是不是就是我们的。
17:22
对,我们指定的glass是吧,去对它的方法去发送这个信息吧,然后呢,我们找到我们的block,那么week block,那么现在这个东西变成了什么?大家注意啊,这个东西是什么?还是我们的block吗?是不是不是了,它现在变成了什么一个函数指针,那么这个函数指针指向了什么呢?大家看到这个取地址符号了没有?是不是前面这一块是对后面这一块的一个类型说明吧,就是这个地方有个取地址符号,这个取地址符号是不是指向了这个函数,那么这个函数是一个什么呢?哎,他们的F搜索一下。是不是这个结构体的一个什么函数。
18:02
一个什么函数是不是它的一个构造函数,那么在这个地方我注意到两点,第一点什么呢?你看到没有,这个IC指针它是指向了take block,那么请问按照刚才我们的三个条件进行一个判断,现在这个block应该是什么类型的block?我们知道OC对象前面是不是有一个默认的杠杠状,所以说它现在是不是有强引用。并且它里面是不是引用了OC的对象,所以说这应该是一个什么类型的。什么类型的不要。来看一下这三个条件,三个判断。什么类型的不拉?来,还有没有其他同学?你们是没看明白吗?还是怎么回事?怎么没有其他同学呢?这个条件都给大家摆到这个地方了。对吧,负这给强引用或者拷贝来修饰,然后呢,是不是使用局部变量,是不是它通通满足,所以说这应该是一个对向的。
19:04
但是呢,微上的lo,你有没有发现它的ISA指针是指向stick的,那么请问这个地方为什么?为什么?然后呢,我们现在看block内部,哎,它里面是不是有这个ISA啊,是不是有这个方程PDRR,这个方程PDRR是什么意思呢。这个方式PR大家可以看到,那么这个东西是不是实际上我们写在block代码块里面的一个代码,那么block代码块里面代码,那么它实际上它是在底层生成了一个。函数。那么这个函数,请问它的一个存放位置是在哪?存放位置在哪?是不是在我们的一个ma o中啊,Ma欧中好,那么现在我们现在有了第一个问题,哎,这个IC为为什么指向我们的stick,然后呢,第二个是什么呢?我们写的在block代码块里面,代码在底层存在一个。
20:02
T的一个静态函数里面对不对?好,那么现在我来给大家回答第一个问题,就是之前有同学问到的。问到的是什么呢?就是说哎,我们的一个global block存在哪个地方,那么首先第一点我们的全局区。在我们的,在不在我们的内存中。来,我提出这么一个问题,全局区在不在我们的内存中?认为在的同学,我们来扣一,认为不在的同学,我们来扣个二来非常简单的一个问题,全区在不在我们的内存中?那么为什么他在我们的内存中,全局区正常了,包括全局区的block,它不是应该在我们的一个ma o中吗?对不对,为什么它会在我们的内存中呢?那么这个东西大家有没有想过,想象过我们编译出来的最后这个可执行文件是怎么来运行的?是不是你要先把它加载到我们的内存中,然后呢,我们的内存再根据指定的一些条件,从这个ma中读取相关的信息吧。
21:07
好,那么现在我再问大家一个问题。为什么OC是一个动态的语言?为什么我们需要long time long time到底是来干什么的?来,大家给我回答一下,如果说不知道的就给我打二,我来给大家解释一下。咱们延伸一下好不好。好。那么刚才我们所说的,那么首先第一点。我们编译出来的是不是一个可执行文件,比方说这个block text,这是不是一个可执行文件,这个可执行文件是不是存放在我们当前的电脑上面了?那么当我们的电脑要去执行这个可执行文件,或者我们手机要去执行这个可执行文件,它需要怎么办?是不是把它拷贝到我的内存里面,是在这个地方放一份?那么放一份之后呢,那那么就有一个问题了。就一个问题,你平常编译出来的这些类呀方法,你有没有发现它是怎么来创建的?
22:02
他是不是。动态来创建呢?它怎么动态来创建呢?它是不是通过我们的over center是不是去对指定的类,包括指定的方法去发送消息,那这些东西是存放在哪呢?哎,我们的马克欧编译了之后,在我们的马克欧内部有一个专门的一个段,在段里面有一个专门的session,那么这里面就是存放着我们OC。的类名啊,你的那些方法呀,你的那些I那些信息,然后当你这个ma加载到内存之后。怎么办呢?我们的wrong time这个动态库就会去到这个段里面的指定的这个session里面去读取这个信息,那么读取完之后把它去转化成我们经常见的。格拉斯RO拉斯RW。那实际上这就是咱们OC动态性一个最直观的一个描述,这个地方大家听懂了没有,听懂的同学给我扣个六六好吧。
23:04
诶,先把咱们的ma或加载到内存,然后呢,从我们我们内存中一个指定的session里面去存放着我OC相关的一些内容,那么这个OC相关的一些内容,哎,怎么办呢?我们runtime去到这个session里面,把它读出来,转化成我们runtime底层的那些glass的结构体,然后呢。是不是就可以动态的去初始化我们的对象了,那么就是这么简单,那么给大家演示了之后呢,那么我们再来看,哎,我们今天的block代码。那么首先第一点我们来到最上面的,我们一个touch比,那么在touch比阵里面呢,哎,我写了一个block。那么首先第一点这个block是不是杠杠位来修饰的,然后呢,里面是不是引用了我们的一个局部变量。既然引用了局变量,我们是不是只能从我们那个堆或者战区的block来进行判断吧,对不对?然后呢,它前面又是杠杠week来修饰的,是不是正好满足?哎,我们的战区的block不能复制给情侣用啊,所以说这是一个战胜的block没有问题吧。
24:11
是不是再上的葡萄河好,那么我们接下来看到第二行。那么在这个地方,我是不是把我们的一个战区的block通过我们那个桥接转化成了一个结构体,那么这个结构体是什么呢?我们点开来看一下。那么是不是就是我们刚才看到的lo结构体里面这个属性啊。那么为什么可以这么转呢?因为很简单,它的底层是不是就是一个结构体,包括我们定义的这些类对象,是不是底层也是一个结构体啊,所以说我可以是这样直接来转。那么这样直接来转之后呢,我们可以看到,那么这里面有两个我们关键要注意的点,那么这个ISA,还有这个in work。那么work就是我们写在block内部的,哎,那那个代码就是我们生成的底层函数,保存我们代码的那个函数啊,那么这个是什么?是不是一个函数指针啊。
25:06
这个指针是干什么呢?是不是就是指向,哎,刚才我所说的。我们写在block代码块里面,代码的这个函数啊。说他帮我生成这个函数,这个地方能不能理解。能理解的同学给我扣个一。我们只要注意这两个地方,一个是它的ISA,一个是什么呢?它里面有一个指针,说保存着生成的这个函数。那么回到这个地方,那么接下来我干了一个什么事情呢?我干了这么一个事情。我现在把这个week block赋值给了前面是一个杠杠strong,修饰的一个strong block,好,现在我的问题来了。这个strong block是一个什么类型的block?这是一个站上的好,现在我给它复制成了一个强引用。
26:02
哎,我这直接来用的,还是用了六。这是一个什么类型的?现在我的strong block是一个什么类型的?来,其他同学也想一下。我看你有没有把这个结构体这个东西弄清楚。哦呦,今天同学不错呢。我都能回答出赞赏啊。这位同学回答是对。那么现在我们怎么来判断,哎,你是不是听过我的课呀,现在我们怎么来判断这个死strong block,那么他正常是前面有一个杠状,它是满足我们成为堆上的一个block。但是呢,你有没有发现,那么lo底层它是一个结构体,那么结构体不只给结构体的话,它是属于什么?哎,做过Swift的同学都知道。结构体复制给结构体,它是属于什么?是不是一个值传递啊。我是不是把我结构体里面的值传递给你啊,哎,比方说我现在这样等于是吧,我现在是不是把我IC的值赋值给你的I sa啊,那么正常的你俩是不是应该是一样的。
27:09
所以说按照这个东西来分析,这个strong block是不是还是一个block。那么怎么给大家验证这个东西呢?那么大家看到我下面这一行代码,这个是不是有一个隐卧。这个是不是保存着我们写在这里面的这个代码。我现在把这个week block,我们战胜的这个block,那么它的work赋值为new。如果现在我再去执行这个strong block,如果说这个strong block,那么报错。报访问不到这个函数指针,那说明什么?这个东西和这个东西应该是不是一个啊。对不对。这个地方能理解吗?是不是如果说我调用它爆破,那说明什么呢?是不是它跟它是一个,也就是说我所说的这个结构体赋值,结构体赋值。
28:04
值传递是不是正确的?好,我们现在在这个地方打一个断点,那么直接运行我的代码。我现在来,我感觉你们都听过我的课是吧?点击啊,点击点击之后呢,现在来到这个strong block,然后呢,我现在往下走,往下走了之后,我们来看到这个地方。我说的没有错吧,是不是它仍然是一个stick block,然后这个week block是不是也是我们stick block战胜的block,然后现在。我们的block in为六,志为六之后,我现在再往下走,是不是报一个坏地址访问,为什么?因为你俩的隐卧是不是同一个?我把它置为new之后,那么也就意味着strong block结构体里面的这个in work是不是也是一个new啊?你访问一个new,他是不是就应该报这个?坏之争啊。所以说这个结构体和结构体赋值,包括这个直传体,包括我们这个block的判断条件,大家明白了没有,明白同学给我扣个一。
29:10
好,那么接下来大家明白之后,那么接下来我再来做一步操作,我来一个的一个拷贝。那么block拷贝之后,那么请问我的一个我的一个strong block是一个什么类型的block?这个什么类型的不知道。好,有同学说对,还有没有其他同学?哎,非常好,今天咱们同学非常不错,这是不是应该是一个对象的,为什么呢?因为在这个地方你手动去调用它copy的时候,你会触发一个block的一个拷贝,那么这个地方就牵扯出了一个block到底是如何拷贝的,那么我们来到这个源码里面,那么在这个源码里面,那么我们直接,哎,咱们不废话,直接看到底层的这个。Block拷贝,那么这个就是block拷贝的时候调用的底层的函数,那么在这个地方大家可以看到我上面的注释,那么拷贝我们的block,如果原先是在堆上引用技术加一,是不是从这一点更印证我们的block底层是一个?
30:13
是一个我们的OC的对象吧,对吧。如果你原先在站上,那么会被拷贝到堆上,然后呢,初始化这个东西我就不说了,如果伯乐河在全局区,那么什么也不干。那么我们可以看到下面它怎么来拷贝的,那么首先第一点是不是它把这个指针转化成一个block layout这么一个东西,我们点进去来看一下。是不是就是刚才我定义的一个结构体啊。那么它转成这个结构体之后,那么他首先干了一件事情。然后大家看到啊,已经在堆上的,哎,引用技术加一,如果在全区什么也不干,那么都判断完了,那么不block现在在站上,那么需要进行拷贝,怎么来拷贝。第一点,通过malo开辟一块。跟我们。是不是这个结构体空间大小的一个内存啊,哎,Melo出现malo是在哪个地方开辟内存呢?
31:06
是在哪个地方开辟内存呢?这个东西你们给我回答一下。是不是在堆上开辟内存的,然后呢,开辟完了之后,他是不是通过memory more将我们的一个。我们在站上的数据全部复制,这个地方是复制啊,复制到我们新的一个result上面,哎,我们开辟的这个堆上的空间,那么复制完了之后,是不是在这个地方进行了一系列的一些复值啊,哎,拷贝他捕获的同源变量,那么最后大家看到这个地方没有。他的ISA是不是现在才去指向了这个lo?好,所以说这点大家明白了没有,为什么不lock?一开始它的ISO会指向它的一个堆上。是不是因为block拷贝其实是一个动态呢?对不对,这个动态的你不运行我怎么再堆上开辟空间对不对,我不运行,你怎么将这个IC针指向malo吧,对吧,所以说初始化的时候是不是都是在战场,然后呢。
32:11
再去拷贝到我们的堆上吧,那么所以大家看到这个地方。那么它触发了block拷贝,那么拷贝,呃,那个什么通过我们malo在堆上开空间,那么所以来到这个地方,我们直接去拷贝的时候,那么是不是就意味着把这个站上的站上的block通过这个函数拷贝到堆上了?好,那么我来问一下大家,我来问一下大家,那么刚才我在这个V的lo里面写的那个函数为什么不会被拷贝到对象,我刚才怎么写的,是不是word?的。来一个冒号,一个上上引号来一个,我等于我们那个。然后呢,我来一个。
33:01
为什么我这样写,这个不落课不会被拷贝到最上?是不是因为它是全局区啊,它是全局区,全局区的block,它是存在我们的ma欧中的,那么这种block比较特殊,因为第一点它比较难实现,比较难实现,为什么你在block内部什么也不写,什么也不补货的话,你首先第一点你写它的一个意义是在哪呢?对吧,然后呢,所以说那么这种情况它不会触发,哎,只有当你是战胜了block,那么才会去触发,变成我们对上的block,我现在拷贝一下。再来运行一下。明星来来。我们现在是站上的,然后呢,大家这个地方还没有负值往下走,是不是malo malo之后,那么也就意味着从这一步开始,现在是不是。多了一个结构体啊。现在strong block这个结构体是不是应该是这个week block这个结构体的一个复制吧,对不对,是不是它的一个复制。
34:06
所以说,我再给这个week block的work赋值为new。我影不影响,Strong不让。影不影响他?影不影响?来,还有没有其他同学?影没有影响,我现在是不是把它拷贝了一份吗?是这个strong block跟我的规格block现在应该是两个东西了吧,是不是应该不影响,所以往下走走。正常的是打印出来了,是没有任何的问题吧。那么来到这个地方,那么大家,哎,感觉好像今天配合的都非常非常不错,那么我们来演示一下,延伸一下。那么在这个地方呢?哎,我定义了几道关于block咱们堆栈的一个面试题,那么我们一起来看一下。那么首先第一点,大家看到在这个block stick这么一个方法里面,我写的这些东西。那在这个地方,我定义了一个杠杠,未可修饰的一个week,但是没有赋值。
35:02
那么在这个作用域里面呢,我同时定义个杠杠week修饰的一个week block1,那么这个block它是不是捕获了我们的局部变量,但是呢,它是一个杠杠weak来修饰的,那么首先第一点捕获了变量是不是只能从堆或者站里面选一种,然后呢杠杠位来修饰。是不是只可能是我们一个赞?没有毛病吧?好,那么然后呢,来到这个地方,我对这个week block没有赋值的,这个block那么负了一下值。那么请问我在这个地方能不能成功的调用?认为能的同学扣个一,认为不能的同学扣个二,给大家两秒钟的时间来思考一下。能不能?好,我来打开,打开一个东西啊,给大家来看一下。好,我们现在直接来运行一下,哎,把它来拷贝过来,拷贝过来放到我们的V底的里面来,直接调一个它的来调用。
36:05
看来直接运行我的代码。来点击。没有报错吧,是不是正常才去报错,那么为什么?那么首先第一点,这就牵扯到了我们的一个账。我们那个赞。我们站,我们stick和我们堆的一个区别。那么我们知道,那么站上的空间是不是也在你的APP运行的时候,由系统动态来分配的,那么系统动态怎么来分配呢?首先第一点,当你去调用这个方法的时候,那么系统会在它指定的一个占空间开辟一个占地址,那么这个占地址什么呢?哎,由高到低,那么这里面保存了你当前方法的一个叫什么是战争。那么这个战争里面就保存了你当前在这个方法里面去初始化去使用的这个变量,那么也就意味什么呢?当你去调用这个方法的时候,我们的系统开辟了战争,当你这个方法结束的时候,是不是你的这个占的空间再由系统回收啊?
37:08
所以说我们知道站上的空间是不是由系统来控制的,它怎么来控制的?是不是当你调用的时候开辟,当你结束的时候会说啊,这个地方能听明白吗?能听明白给我扣个一。就调用开辟。我们的结束是不是回收啊,那么所以大家可以看到,在这个方法内部,我们这个week block,它的一个作用域是有多久。是不是整个方法这么久啊,那么我们关键的就是看到这个地方。这个地方刚才我是不是说了block等于block,它是一个什么,是不是就是一个结构。赋值吧。赋值。所以现在干了一个什么事情,我是不是把week block1赋值给了week block2,他俩现在是不是一样的?是不是一样的。
38:01
那它既然是一样的,那么就意味着什么呢?我调用week block是不是实际上就是调用这个block代码块里面写的代码吧,对吧,所以这个地方。大家没毛病吧?哎,那么我们再来看什么呢?我们再来看我们追上,哎,刚才这位同学说。那么堆上的这个同样还是刚才我们这样来写。这样来写,那么首先第一点我们来到这个地方,那么还是杠杠位修饰的一个week block没有赋值,然后呢,再来到这个作用域里面,那么我们可以看到我现在定义了一个杠杠strong修饰的这个strong,那么里面同时捕获了我们的局部变量。那么所以说这应该是一个malo类型的block,没毛病吧,没有问题吧。然后呢,现在在这个地方,我是不是同样进行了一个赋值,是不是跟刚才一样,那么首先第一点。刚才是不是我们。我们站上是不是负值,现在是不是变成了堆上负值,那么请问一点。
39:02
稳一点。我现在这个赋值。还是不是结构体的一个复制?胃block和子状block,它俩代表的是不是同一个东西?是不是同一个东西。是不是是呀,为什么?因为它本质是不是还是一个结构体复制啊,你不要受这个杠杠胃壳影响哦。结构体赋值,我是不是把我的I sa复制给你啊,你的I sa是不是现在也指向一个对象,好,那么现在我问一下大家,这个地方运行会不会出问题?好,这位同学说会崩溃,还有没有其他同学说这个地方类型会不会出问题?会不会出问题来?来给大家看一下,来五。零。
40:00
共产主义啊,你的名字我不敢读呢,还有没有其他同学,就算咱们这两位同学吗?这个我运行会不会出现问题?没有同学来回答吗?啊,没有同学来回答,K老师来回答一下,那么首先第一点我们知道对象的对象,他是不是会有作用欲的。那么有作用欲的,那么首先第一点,当它出了这个作用欲之后,我们对象的这个对象是不是会释放,那么会释放了之后,我的wake block和这个strong block竟然是同一个东西,我现在在这个地方调用一个已经释放了的对象。这个地方能执行出来吗?是不是依然会报那个坏指针访问啊,对不对,呃,那个嘛,对吧,坏指针访问,那这样为什么呢?那么首先第一点我们再来看一下这个码。我们看到这个源码lo在进行拷贝的时候,它是不是通过malo在堆上开辟的一块空间?那么首先第一点,那么有malo必有一个什么函数?
41:03
会有一个什么函数?是不是辅瑞啊,那么所以我们看到block这个函数。那么在这个函数里面,那么大家看到对block做release操作,那么block在堆上才需要release,哎,其他地方不需要,它是怎么release呢?那么首先第一点大家看到这个地方,哎,判断需要不再推上,那么如果你的一个引用技术减到了零,那么表示block需要销毁,怎么销毁的呢?是不是福瑞啊,是不是福瑞好,那么这个地方我要转头再问大家一个问题。我们来到这个blog拷贝,那么首先第一点。在这个地方block被拷贝到追上之后,在这个地方被block被拷贝到追上,那么我想下站上的block还有没有存在的必要?还有没有存在的必要?
42:02
没有吧,对不对,我拷贝已经过去了,并且我把所有的空间是不是都复制给你了,并且你在站上的对象,你是不是出了这整个方法的一个战争是不是就被销毁了。所以说你是不是并没有存在这个必要,哎,所以我们来到这个地方,那么他这样调用是会爆破爆破。我们来调用一下,看一下。哎,把它放到个地方来卡的加热来运行。是不是直接报一个坏地访问好,那么这个地方我再给大家加深一下印象。那么当你在站上,当你调用一个方法的时候,那么我们。的系统会在站上专门给这个方法开辟一块占空间,开辟一个占空间,那么这个占空间里面,哎,存放了你的这些局部变量啊,这些东西。那么这个东西存放到站里边,那么也就意味什么呢?哎,当你调用这个方法的时候,开辟这么大一块占空间,那么当你这个方法调用完了之后,这个占空间是不是要用系统来回收啊。
43:08
那么也就意味着你在这个占空间里面定义的这些临时变量,植物变量,它会被怎么办?那怎么办?这怎么办?被回收吧,对不对,他是不是也会被回收被销毁啊。那么但是我们追上了它是怎么回事呢?追上是不是出了作用欲之后就会触发?我们的椎是不是进行一个回空间回缩啊,那么所以说在这个地方。这个堆和站的这个区别,大家听明白了没有听明白的同学给我扣个666好吧,所以说这个东西对你理解还是非常有帮助的,那么我们来这个地方,我们简单来看一下当前的这个战争。我们通过Di-F-M-F就是查看当前战争,杠F是什么呢?查看当前的汇编跟我们的源码混合的这么一个形式,我直接来回,呃。
44:05
那么大家看到这个地方。看到没有RSP啊,什么什么,是不是他在这个地方double q是不是就来通过RP开辟这么大的一块战争啊。开辟完了之后,是不是来到这个下面再进行一个回收啊。是不是整个是这么来进行一个操作的。好,那么在这个地方,那么首先第一点,那如果说你对这一块想要再来了解的话,哎,比方说你想干什么呢?诶研究一下lock是怎么拷贝它的一个成员变量的,诶就是通过这个方法来进行拷贝的,你想要好好的去研究一下,那么你拿到我今天给大家这份源码好不好,这个源码里面我做了非常详细的一个重。并且呢,这份源码是可以编译运行可调试的,那么大家也可以看到我刚才是直接运行起来的。那么这里面主要是大家想明白一个问题,给大家暂停一下,想明白一个问题。就是这个block雷奥里面。
45:01
你不是这个in work保存着我们写在block代码块里面的代码吗?对不对,那么大家想一下我block。我主要好客的是什么?是什么?来,我问一下大家。好客的本意是什么?是不是把我要调用的这个代码替换成我自己的之后再调回他原先的吧?对不对,那么所以说我耗的是什么,我是不是只要把它给替换掉之后,换成我自己的,然后再把它保存一份,再调用它是不是就可以了。所以说捕捞号的一个原理,那么就是这么简单,就是这么简单,但是说它里面复杂的是什么呢?那么第一点。我们知道block在这里面,我们的block是不是可以传递参数的。那么传递参数也就意味着你保存的这个函数指针,它的后面是不是一个不定参数啊?所以说你是不是不好根据这个不定参数去动态的去创建这个引用work吧,所以你需要一个什么。
46:07
需要一个什么?是不是一个labor?F,哎呀,Label f Fi可以干一个什么事情是吧?可以动态的调用和创建我们一个C函数吧。就给我们的C语言添加一个运行词啊,是不是给大家扩充这么一点知识,那所以第一点,那么今天给大家提供这么一个block的一个源码,然后呢,我再给大家提供一个什么呢?提供一个编译命令这么一个文件,那么这里面主要是讲解,诶,咱们的源码到底是同样通过咱们的。诶,咱们的LD的哪些参数,把我们的源码最后编译成ma o的,这里面非常非常详细,你在网上都找不到,并且我里面做了详细的一个例子。怎么在我们的模拟器,怎么在我们的Mac上面编译,怎么在我们的真机上面编译,通过指定什么参数,怎么在编译的时候同时去链接相应的指定的I库,那包括呢,怎么去生成DSY文件,是不是好多同学对这个东西不了解嘛,那么你生成一下看一下,然后呢,再通过我告诉你的这个命令来查看一下DSY目到底保存了什么信息。
47:12
PSY保存什么信息?来,我问一下大家面试题。为什么?哎,我恢复符号的时候需要DM信息这个文件。DSY保存了什么?没有同学知道吗?你们你们那啥我不说了,你们这都不搭理我,我就不给大家说这个保存什么了啊。好,那我接着说了啊,查看方法的一个内容,包括整个的静态库的压缩,解压缩是吧,怎么创建静态库,怎么创建动态库,怎么查看符号表,哎,怎么去生成DS文件。那么怎么去移除指定的符号,包括哎,怎么去进行这个二进制重排好。那行吧,那泰老师不是这样的人,那我给大家说一下,那么DS文件它本身保存的是什么呢。
48:00
保存的是我们。注意保存的是指什么?我们分配了虚拟地址的这个符号信息。我们知道我们的ma o是不是加载到内存的时候,由我们的DY去进行加载的时候,它是不是会干一个贝这么一个操作,其实干什么,是不是给每个地址添加这个as SL ralr是什么。是不是添加一个偏移量啊,对不对。那么当你真正崩溃的时候,你是不是能获取到这个符号信息吧,崩溃的这个符号调用站吧,对吧,那么这个符号调用站。那么配合着DM里面保存着这个没有偏移的虚拟信息,那么就能把这个符号电站它里面真实的这个符号。恢复出来。那么首先第一点这个地方就有一个问题。我们知道崩溃的时候里面保存的是什么,是不是偏移之后的?
49:01
偏移。偏移。偏移之后的。虚拟内存地址吧。然后呢,我们的DSYM文件保存什么呢?保存着没偏移的。不让我写,不让我写,我不写。没。偏移的。虚拟内存地址吧。和。这个地址代表的符号信息吧。号信息好,那么请问一下大家。偏移之后的怎么对应上没有偏移。怎么对应上没有偏移的,哎,他加了一个偏移,主要是为了安全嘛,对吧,你为了你加上这个偏移量之后。咱们的那些黑客就不能直接通过这个没有偏移的去获取到指定的符号信息吧,对吧?好,我现在就问大家一个问题,偏移之后的虚拟内存地址。怎么能变成没有偏移的虚拟内存?
50:00
怎么变成很简单。来,大家来思考,也就是说,我的DS文件为什么能恢复偏移之后的虚拟内存?是不是只要你这个偏移之后的虚拟内存里地址里面保存一个信息,是不是你的偏移量可以了。这不就这么简单一个事儿啊,所以说你看到你的DSY文件里啊,不是你的崩溃符号日志的那个信息里面,它里面都是保存着一个偏移量啊,保存一个偏移量,然后呢,你所有偏移之后的虚拟内存地址,减去这个偏移量,就等于DS文件里面保存的没有偏移的虚拟内存地址。那么通过这种方式就能恢复这个符号信息,你明白没有,是不是很简单一个问题啊,大家听明白没有?所以说咱们今天cat老师给大家提供的这个资料,哎,包括还有今天咱们使用的脚本,哎,非常非常的有帮助,所以说有需要的同学咱们可以加一下咱们今天的数理老师来获取一下这个资料好不好?
51:01
好不好,包括这个编译命令啊,编译编译编译命令,为什么我非常推荐大家去拿到这个东西,就是因为你可以很简单的去编译一个文件来看一下。好,这个刚才我们是讲了一个堆栈的,那么我们接着往下看。我要看。好,这个我也关掉,关掉之后。那么首先第一点。我们看到在这个地方,我定义的一个。Block,那么首先第一点这个block是不是杠杠week来修饰的,然后呢,这里面是不是捕获了我们的局部变量A,所以说这是一个什么类型的block?是不是应该是一个什么类型。你们再不说我就挑出来了啊,什么类型。什么类型?你就不说是吧,是吧,赞上的block对吧,然后呢,在这个地方呢,我通过迪斯after去调用这个赞上的一个block,那么请问我现在这样写能不能调用成功,能不能出问题,会不会出问题,这会的同学扣个一,认为不会的同学扣个二。
52:04
会不会出问题?战胜了不block啊,它的作用欲只有我们的方法的空间这么大的一个作,呃,它的一个生生存周期是只有这么大。会不会出问题?After延迟三秒会不会?我们现在直接来运行一下。还拷贝到这个地方。拷贝到这个地方之后,很慢加而来运行。312。是不是直接报一个坏地之房呢?为什么呢?怎么来解释这个东西,那么当然我们知道PA啊,不是我们的一个take block,它的一个作用率是不是只有这么大,也就因为什么呢?就出了这个方法的作用率之后,我们这个block就被销毁了。那么但是呢?我们这个捕捞是不是被这个捕捞给捕获了,那么为什么。这个dispatch block没有去持有我这个战胜的block呢。
53:04
来,这是我想问的一个问题,为什么?你们都知道捕捞会补货变量吗?那么为什么他没有?请问一下为什么他没有吃?大家回答一下来。还有没有同学,因为是站上。Week。那么这个东西主要跟什么有关呢?哎,跟我们的一个杠杠胃口有关,好你现在说是说是站上好,我现在干一个事情,我来一个。来个boy。上线一个状。然后呢,等于我们一个。这个不拉。我现在把它变一下,那么请问我现在调这个strong。
54:02
会不会报错?会不会报错?我现在调这个strong block会不会报错?来会不会会不会啊,大家有点纠结是吧,来我们直接看我的价格来运行。报错了没有?报错了没有?来报错了没有?在公屏上告诉我有没有报错。没有吧,好,那么你刚才说跟这个block有关系,那么请问这个是不是这个block。是不是仍然是这个block吧,那为什么我在这里面调用这个block,它不像调用我们原先的,没有复制之前报错呢。那么这个地方主要跟什么有关系?不要跟我们的一个杠等微课有关系啊同学们,为什么呢?不知道大家有没有注意,一开始的时候,我们生成这个C加加文件的时候,诶,大家有没有注意这一点,我现在加B来编一下。
55:08
那么大家看到我此时的这个block里面,是不是捕获了我的week self?那么捕获这个weak self,不知道大家有没有注意他是怎么补货的,我们讨论一下下件。在这个地方,他是不是把我们的self作为他的一个成员变量传递进去了,他怎么补货的来往上走往上走。你看到没有。当你是一个杠杠week修饰的,它捕获进来,成为它的成员变量是不是仍然是一个杠杠week来修饰的?并且你在调用的时候,是不是仍然也是一个杠杠week来修饰的?那么所以在这个地方,我们是不是就能得出一个结论?当我们的捕捞。我们的堆上的block补货一个变量的时候,它是怎么补货的?
56:00
是不是杠杠未可?你是杠刚位的,他补货进来是不是也是杠位的,那么同理你是一个杠杠死状。你补货进来是不是也是一个创造状。那么所以在这个地方,为什么我的block并没有报错,是不是就是因为在这个地方默认它的前面有一个什么一个什么?就默认有一个杠杠死状的。那么所以说这个strong block被我的迪block捕获进来。他是不是在这个地方。变成了一个杠杠状,也就是说他是不是对他进行一个强持有了。强持有了也就意味着什么,是不是它的引用技术加一了。这个地方能听明白吗?能听明白的同学给我扣个一。本来你是你是不是杠杠死strong被捕获进来,你这个地方也变成一个杠杠死strong了,那么你变成一个杠杠死strong,是不是我当前这个结构体对你进行一个强持有,强持有了。
57:04
是不是对对你的引用技术加一了。那么所以说在这个地方它不会报错吧,但是呢,我如果直接调用。它是不是一个状告未可修饰的,那么就是一个若持有,若持有的话。是不是我捕捞和并没有对他进行持有,并没有对他持有,所以说这个地方是不是直接就会报错呀。所以这个地方你听明白没有。那听明白了之后,那么我反过头来来看一下,就是一开始的时候。跟大家说这个面试。那么为什么?还记得没有,就在这个地方,它输出的是一个三啊,那么我们来计算一下为什么输出一个三,首先第一点,我初始化这个对象的时候,它应该是一个一吧,这个没有问题吧,没有问题的同学给我扣个一。做初始化这个对象的时候,它count是不是应该是个一。然后呢,他被这个捕捞补货的时候。他现在变成了一个什么呢?我现在把线换成我们的一个啊,来慢慢的加来运行。
58:03
增加预警。我们来看到这个地方。看到没有,它补货进来,是不是也是一个杠杠死状来修复的,所以在这个地方它是不是变成了一个二啊。然后呢,变成了一个二之后,那么大家看到在这个地方。我们保存block代码块里面代码,它在这个地方是不是又定义了一个C去接收他的这个成员变量了,所以说在这个地方它变成了一个三。所以知你知道没有,现在这个三怎么来了没有。听明白的同学给我来扣波六六好吧。清晰吧。很清晰吧,是不是。这个三是不是这么来的。那么现在接下来我们再来干一个事情,我们再来看一个。那么首先第一点。嗯,这个地方是不是就可以了,这个地方是不是给大家讲清楚了,这个三是怎么来的。好,那么接下来我们再来看这个这个代码,那么现在我把这个地方关,呃关掉,关掉之后呢,我们再来看第二个,我们再来衍生一个题。
59:07
那么这个题跟刚才是一样的,那么现在我变成了这个。我现在不是week block,前面没有杠杠来修饰,它现在应该是一个melo block,那么现在我再去这样调用是不是就没有问题了,为什么?你前面是不是一个杠杠死状,被我的这个补lock捕获进来,是不是会产生一个强引用啊?所以说这一块会正常来输出没有问题吧,没有问题的同学扣个一。好,那么来到这个地方,我反过头来再给大家加深一个印象,加深一个什么印象呢?就是加深一下。咱们在站上的这个变量释放的一个空间,那么我来到这个地方,我来到这个地方。那么当我执行到这个代码的时候,我让他干一个事情,我在这个地方让给他添加一个wrong。那么这个run入呢,我添加了一个三秒,也就是说三秒钟之后这个run入会超时。
60:04
那么再一个地方,我要给大家普及一个入的一个知识。首先第1.run,洛普再去run的时候。当它里面没有什么东西要处理的时候,它处于一个什么状态?是不是处于一个睡眠状态?睡眠状态,那么睡眠状态他会干一个什么事情?是不是阻塞block住当前的?县城吧。县城是不是那么lock住,堵塞住当前的县城,那么实际上也就是干了一个什么事情。说把我正在运行的一个代码给暂停掉。那么所以说我来到这个地方,我让当前这个代码暂停运行三秒钟。那么现在。我的这个战胜的block,我的杠杠未修饰的block在这个地方能不能正常打印出来?能不能?我们来分析一下,那么暂停了三秒钟之后,我站上的这个变量是不是就延迟了三秒钟来释放,那么延迟三秒钟来释放,是不是正好去满足我第一次after这个三秒钟吧?
61:13
所以说那么他是会正常的打印出来的,我们来看一下是不是正。慢的加运行。那再来我点击。来,现在是不是卡了三秒钟?就阻塞当线,哎,是不是正常的运行,所以说你现在明白了战胜了变量的一个释放周期了没有。这个地方应该听明白吧。听明白的同学给我扣个六六好吧,这个东西你不是一直不理解吗?对吧,所以说今天cat老师给大家讲明白了。那么讲明白之后呢,那么接下来我们来讲这个杠杠胃口和杠杠状的。这个本质原理,那么首先第一点我们回到刚才这个问题,回到刚才。那么。第一点。我问大家,就是我们今天这个面试。
62:00
站上的不浪头会不会不会变量。我们刚才说过了,是不堆上的补block,它是不能捕获变量,那么首先第一点战胜的block能不能捕获变量?我们刚才讲了那么多。能不能?是不是能的,是不是能的,哎,他不光是能的,并且他是不是也去遵守这个规则呀,是不是也去遵守这个规则,那么只不过为什么战胜的block,它不会导致那种循环引用呢?哎,不会导致那种强强引用呢,因为战胜block它的作用域是不是只有这么大呀。我没办法对你持有更长的一个时间吧,对吧,我出了这个方法之后,我是不是被系统干掉了,我怎么再去强持有你啊。这个地方大家听明白没有?所以说我现在这么写,我给大家演示一下啊,今天我非常非常高兴啊,大家配合的非常非常好。
63:00
所以说我讲的东西就会非常非常详细,我现在来写一个什么呢。的一个多。我来带家写说我,哎回车,回车之后,我现在来干一个事情,你现在不是copy来修饰的吗?我把它改成一个对。改成week之后,然后呢,我在这里面使用。如果是copy的话。这个地方会不会报循环引用。会不会?会吧,对对,是不是会报循环引用吧,对吧,好,那么现在我把它改成未之后。那么成为了week这个self的work,它是不是就没有强引用了?没有。没有强你用了吧。引用。并且呢,他又捕获了咱们的OC的对象。所以说他应该是一个战胜的标准,没有问题吧。
64:03
好,那么现在我们来运行一下,哎,我怎么给大家判断有没有强引用呢?那么首先第一点我在这个dio里面有。有打印的。我先来干什么呢?我先来直接运行我的代码。正常的没有问题,那么首先第一点我来到这个地方,我打一个断点,打一个断点来点击。点击之后。多克现在是不是确实是一个战胜的block吧,对吧?这个赞吧。对不对。是不是是不是,同学们是不是是不是,是不是。活性啊,来跳过。跳过之后我的代码是不是正常来运行,我现在返回。哎,带到了没有。是不是带到它了,所以说再堆,包括我们的。这个我们的麦lo大家应该能详细的分清楚了啊,详细的分清楚了。这个地方你们再出去遇到这样的面试题,不要给我回答错了好不好?不要给我回答错了。
65:01
我现在把它关掉这个地方大家有什么疑问没有?没有的话,我们接着往下讲啊,那么首先第一点我们看到这个这个。那么在这个地方,我通过一个杠杠week,那么修饰了一个weak self,对不对,修饰了weak self之后,那么现在我定义这个全局的静态变量,全局的静态变量来接收我们的这个这个调。那么请问。我现在把我们的杠杠未可修饰的self赋值给这个全局的静态变量,我现在这么写有没有问题?这个鞋有没有问题?把这个地方来调一下。我这样写有没有问题?我把杠杠未可修饰的这个变量,杠杠未修饰的这个变量赋值给一个全局的静态变量,有没有问题?那么这个地方它牵扯到一个什么问题?我们知道全局的静态变量,它的一个生命周期有多长?
66:05
是不是跟随?跟随。APP的生命周期啊,对不对,也就意味什么呢?你只要不去手动的销毁这个变量,它是不是一直都存在啊。那么然后呢,我把这个杠杠未可赋值的weak self赋值给了他之后,那么也就意味着什么呢?我现在这个self不就代表这个weak,那么这个地方本质要考察的是什么呢?是吧,这个地方会不会造成这个循环引用啊?就换引用。那么这个地方就要牵扯出了一个问题。那么我们知道杠杠未可修饰的变量,是不是把它修饰的变量放到我们全局的一个弱。你用。表中吧,对不对,那么大家有没有想过,当你去使用的时候。那么它实际上使用的是什么呢?你定义的时候是把它放到若引用表中,那么当你使用的时候,你应该是什么?
67:06
是不是在从这个若引用表中把这个调取出来吧,对不对。所以这个维克要素你使用的时候,本质上是不是就。要。那我现在这样写,那么请问有没有问题。有没有问题?来大家给我点反馈还是没有吗?还是没有吗?你们不在胡说吗?是不是有问题了,为什么你跟随生命周期的一个变量,你怎么能赋值给我们的赋值给了CF之后,我的CF还能去正常释放吗?是不是不能啊,所以说我现在把它改成。然后我们看一下我当前的控制器能不能正常释放。现在点击来返回。
68:01
是不是毛都没有输出啊,然后现在他是不是输出了一个带lo,为什么输出了一个带。是不是因为你第二次点击的时候又去执行了这个代码,它是不是重新创建了一个控制器,又。复制了一次。那么它赋值了之后,是不是把之前负的这个值覆盖了,你前一个控制器是不是就释放了,所以说现在打印的这个dio是谁释放了,是不是前一个控制器释放的。对不对。所以说你看到没有,这个地方是不是有循环引用,是不是有引用的一个问题啊,所以说大家再去使用这个局部的,再使用这个静态变量,或者说咱们全局变量的时候,你应该怎么做。一定要记住,当你不需要他的时候,一定要干一些什么事情。是不是手?动。销毁啊。哎,主动释放你们说的比我好,手动释放吧,对不对,所以说我这样写,哎有问题,问题的点在哪?状况为何修饰的时候你是把self要放到若引用表中,然后呢,你使用的时候是不是又从若引用表中把self。
69:12
取出来,所以这两句话大家能记住吧。记住了之后我们应该干什么事情,那么我们接下来就来讲这个。Weak dance。为什么呢?那么首先第一点我觉得是有两个地方可以颠覆大家认知的。第一个是什么呢?就是。这个地方哎,放到弱引用表中,再从中引用表中把C取出来,那么再一个是什么呢?再一个就是刚才我们说的block。能量容block会捕获变量。是不是堆上的和站上的都会补货?变量怎么补货的,是不是有一个原则?杠杠未可修饰的,哎,补货进来是不是就是杠杠未可修饰的,杠杠死状修饰的是不是补货进来就是杠杠死状的?这两个点我觉得大家平常在一些文章或者博客,或者说你没有去深入学习或者实践的话。
70:03
这两个点还是。大家还是比较难,难去知道难去理解的吧,对吧,这也就是为什么你平常在去写这个quick strong dance的时候,你不知道什么时候里面该写诉状,什么时候里面该写这个。Week吧,对吧,那么所以说大家想不想跟着我再来去好好的来学习一下这个week strong。我在这个地方还给大家准备了一些更有趣的一些面试题,想不想好,那么大家既然想学习的话,那么在这个地方,那么首先第一点我问一下大家。大家跟着我学习的咱们之前的内容,大家大家觉得今天这个课怎么样?有没有收获,有没有收获?那么大家想不想按照这种方式去学习一些咱们is底层,包括OC的底层,包括所有的底层更进阶的一些东西,想不想?那么如果想的话,那么在这个地方我给大家介绍一个咱们逻辑教育专门去给大家提升相关is开发技能的一套课程。
71:07
那么在这道课程里面,那么首先第一点,咱们今天讲的block,就是咱们V14哎,即将要开班的大师班里面的一个内容,那么今天咱们有哪些东西没有讲,那么首先第一点咱们讲了block的本质,讲了block的存储率包,讲了咱们block捕获对象,但是呢,我们刚刚block没有讲。那么同时底层的浩客我们只提了一下,那么这个地方我问一下大家。那么为什么block里面修改变量的时候需要杠杠block?是不是本质上还是因为这个堆栈的一个关系啊,为什么。因为我们来看一下这个代码。当你在这个里面去修改这个A的这个变量的时候,A在哪个地方,是不是在站上。那么在站上也就意味什么,是不是他出了这个动域之后,这个A是不是就释放了。那我这个block它是延迟来使用的。
72:03
你这个A释放了之后,我在这个block里面还会还能修改到你这个变量吗。是不是修改不到了,所以说我需要怎么办?是不是通过杠杠不block去修饰,把这个A是不是拷贝到一个不会去。我控制不了释放的一个地方吧,对不对,所以说你明白了这个刚刚block一个最本质的一个意义了吗?明白的同学给我扣个一。对呀,所以说你发现没有,你去理解了这个堆栈之后,你其实再去理解普拉内部的这些原理很清楚,哎,为什么?因为你知道了它到底是怎么实现的,那么同时大家可以看到大师班里面内容。上来给大家讲的就是对象,那么这个对象里面,诶,咱们今天刚才提到的glass r w-t glass RO-T的一个分析,那么这个分析就是我说的咱们的一个内存中,哎,首先第一点把咱们ma o加载到内存里面,那么加载到内存之后,那么wrong time根据指定的session指定到。
73:05
咱们那个。呃,再指定到咱们那个里面,哎,去读取咱们OC运行时相关的信息,然后把它去转化成底层的这两个结构体,同时大家注意啊,在IS14是不是对这一块又进行了一个更新啊,它更新点在哪?是不是它通过去读取它的偏移量,而不是像之前去读取那个指针了吧,这样有一个什么好处?是不是你指针再去寻址的时候,你要按照这个64位那种方式去寻址吧,你要按照64位,是不是它要占你底下的内存的这个空间吧。那么你按照它保存的偏移量,是不是相对来说你的一个应用程序再去使用这个内存,是不是它使用的更小了,那么这是苹果做的一个优化,IS14做的这个优化,那么这一块大家一定要去关注,为什么呢?因为现在面试是以开放性为主,开放性为主他就会问你这些东西,问这些东西他为什么要问?
74:01
就是看一下你有没有去跟上现在时代的一个发展,现在二四发展。那所以哎,包括这个属性property list ever list这个地方一开始存在哪一开始存在骂里面,然后呢,有我们的wrong,由我们的runtime去把这一块给读取出来,读取出来之后呢,去转化成我们的一个I list。哎,这一块一,呃,咱们感兴趣的话,一会我给大家演示一下,哎,这一块到底存放在哪个地方,马翁的哪个地方好,然后再来一个方法,哎方法签名啊,什么over medicine,哎,他整个消息发送的流程啊,包括他怎么来耗。那么这个是什么呢?这个本质上就是我们的一个动态插桩,对不对,你平常是不是获取这个方法的执行的一些信息啊,是吧,你去买点,那么如果你能耗over,那么你所有的买点是不是都可以转化成这个无买点。哎,包括整个发送流程,包括协议啊分类,分类这一块主要跟什么有关系。
75:00
跟这个咱们的静态库有关系,为什么呢?因为分类是动态创建的,那么动态创建也就意味着。我们的静态库加,再去加载我们的应应用,再去加载我们的静态库的时候,它是不是有一个原则,当你静态库里面的代码,我的应用,我的APP里面没有使用到的时候,他会干一个什么事情?把这个代码静态库里面代码移除吧,对吧,那么移除也就意味着你这个动态创建的分类是不是也会被移除啊。那么所以你需要指定一个什么参数,是不是杠openc,或者杠一个outlo,或者是一个什么bosslo吧。通过他去告诉他我这个静态库里面到底哪些代码需要被加载到APP里面,对不对,那么这都是面试,包括平常开发你要去注意的点,哎,来到这个DYLD,那么DYLD这一块。那么我就不多说为什么,因为你的APP,包括你的动态库的加载,是不是都是由他来进行控制的。
76:01
那么整个的这些原理学习完之后,那么大家可以看到有一个核心编程,那么这个主要是讲解咱们一个把这些原理用到我们的开发,诶怎么去优化我们的启动,怎么去优化我们的内存,怎么去优化我们的界面卡顿。怎么去优化我们的架构,所以说整个的这些东西,那么就构成了咱们微14的一个大师班级,那么咱们V14还有Fla高级建班,哎,这里面主要是讲解咱们的Fla一些实际开发和咱们的原理探索,原理探索主要是给大家提供一个加分项。那么还有咱们的Swift,哎,刚才有同学问,那么Swift的一个loure跟OC也是一样的吗?哎,完全不一样哦,同学们不一样哦,那么这里面怎么来实现呢?哎,在咱们所谓的高级精英班里面也会详细的来讲,那么最后一个课程,哎,咱们的数据结构与算法班级,那么这个数据结构与算法班级里面,哎,主要是帮助大家去应对咱们大场的这个数据结构与面试题,同时教大家怎么把这个数据。
77:00
机构用到实际开发。你比方说咱们今天这个弱引用表,那么它底层是不是一个双向链表来实现呢?好。面试题奥,为什么他要用双向链表来实现?为什么他不用站,为什么他不用追,他要用双向链表呢?是不是这都是面试过程中?容易问到一个点,那么所以说整个的这四门课程构成了咱们的微14。那么这个地方大家注意,如果说你最近有面试需求啊,如果说你最近有学习这个需要,那么你想要了解一下现在市面上is开发应该掌握哪些技能,那么大家可以加一下咱们的客服老师来获取一下这个课程大纲,那么同时如果对咱们微14课程感兴趣的同学,那么你也可以添加咱们的客服老师,拿到这个课程大纲来针对性的来看一下到底有哪些东西,哎,你不了解哪些东西,你没有掌握哪些东西是现在市面上热门的技术,但。
我来说两句