00:07
好,那么欢迎大家来到逻辑教育公开课,我是今天讲课老师K,那么今天我们主要来讲解一下咱们不唠的一个底层原理,那么首先我们先来看一下咱们今天这节课的一个呃课程内容,那么首先第一点我们block与堆战的一个探究,那么我们知道block在本质上,那么实际上就是由他在堆还是站上所引起的它的那些变化。然后呢,我们再通过这个block与堆栈来看一下咱们block的一个底层原理,那么重点去学习block的三种类型,同时明白什么场景下会触发捕捞和拷贝,那么以及诶,我们经常在面试我的开发的时候遇到问题,循环引用到底是怎么产生的,以及怎么来解决,以及我们从上面四个知识点那么衍生出来的,哎,我们这几道一个面题,那么同时咱们今天在课堂上听课还有一个福利。那么我会在咱们今天课程的一个结束,那么给大家来讲一下如何去调试我们pass的一个源码,大家听清楚啊,就讲一下如何去调试咱们酷帕的一个源码,那么感兴趣的同学我们来扣个六六好吧。
01:17
那么首先第一点,首先第一点我们先来看一下,哎,咱们block的一个本质,那么我们知道block在我们OC中,它本质上是不是作为一个对象的形式存在的,你比方说我现在来写一个block。拉。哎,BLCK,然后一个Y。等于来。这样来写,那么现在我们就是定义了一个block,那么我们知道作为我们OC的对象,那OAOC的对象,它的IC指针是不是都指向我们那个NS,我不那么所以说我为了验证block,它作为一个OC的对象,我可以怎么办,我是不是可以重新去改写咱们OC的第四方法?
02:02
那么这个方法我们可以看到,可以看到它在这里面判断了一个类名,那么如果类名是这三个的话,那么它会输出一个什么,输出咱们block的签名,那么以及诶,它所在的类和当前的一个self,那么所以说我们现在直接就来试一下,那么有没有调到这个方法,那么第一点我们来到当前的一个view controlr了,我直接通过我的一个NS。Is object是不是你没有指定通过百分号艾默认是不是就去调用一个对象的第纯方法,那么所以说我这样写了之后,我来到I这个迪斯,我在这个地方加一个断点,加一个断点之后直接卡的加来运行我的代码。运行我的代码之后,那么大家可以看到是不是此时我的迪斯进来了,进来之后我们来看一下当前的这个self。是不是从这个地方进来的,哎,好像并不是,并不是,我们先把它跳过,跳过之后把它跳过,为什么呢?因为我还没有点击这个点击跳转,那么点击跳转之后才去跳到我当前的VICTR,所以说我现在再把这个断点加上,然后呢,来点击,点击之后呢,诶,现在来到这个地方,来到这个地方我们往下走。
03:17
怎么在这还加一个断点,往下走,往下走。好,那么此时我是不是来到了迪斯方法,那么从这一步操作是不是给大家验证了,那么布lo在我们OC中,它是不是确实是作为一个对象?对象形式存在的这个地方能不能理解?我刚才这一系列操作能不能理解,能理解的同学给我扣个一,是不是确实作为一个对象形式存在了啊,并且呢,你可以看到当前的一个self的一个ISA是不确实指向我们的N不在的,并且它的一个类是不是正好是我在这个地方写的这个三个类其中一个,所以说我往下走,那么它正常的是不是会打印出什么呢?打印出当前block的签名以及其他的一个内容,所以我现在回车,那么大家可以看到是不是当前是一个global block,并且它的一个方法签名是一个什么。
04:13
哎,是不是一个Y的没有返回值,它的一个arguments是不是只有一,那么block默认的这个参数是不是它的一个self,然后呢,是不是argument,艾问号是不是一个self self是不是一个N的类型,那么所以我们从这点看出了block确实作为一个对象,那么接下来我们现在有点疑问的是什么?我当前打印出来的这个block是不是一个个global block。那么请问如何去判断block的类型呢?那么首先第一点我先把这个block注掉,那么我们来看一下我当前的will CTR,有一个用copy修饰的一个都。那么我直接来到这个地方。我的一个。Self的一个do等于他回车之后,回车之后,那么请问现在这个C的都沃是一个什么类型的block?
05:04
来我们的,一来一个个。二我们来一个lo。来三,我们来一个take block,请问当前的用copy修饰的self是一个什么类型的block?请你们在公屏上告诉我。立刻,哎,半浮生有一个一,还有没有其他同学?化蝶是一个二。我当前的block是不是作为我当前we controlt的属性,并且是不是copy来修饰的,那么按照我们平常所知的这个copy,那么copy之后,那么他肯定是不是把一个block copy到我们那个站上了,那么所以我们就来看一下,哎,当年self block是不是在我们啊copy到堆上了,是不是在我们的堆上,我点击点击之后呢,我往下走。现在block已经赋值,我现在打开我当前的self CF的do是一个什么类型的block,来大声的告诉我是一个什么类型的。
06:06
是不是一个global block,好,那么现在就牵扯出了一点,为什么copy修饰的一个。Block是一个lo block,那么首先我们要弄明白这一点,我们必须要知道,那么block的一个底层,那么到底是一个什么东西?那么我们知道block在我们OC中,它作为一个对象,那么在我们OC中对象的一个本质是什么?有没有同学来告诉我,对象的本质是什么?对象的本质是不是就是一个结构体呀?那么我们的block它的一个底层,那么也是一个结构体,那么我怎么来给大家验证呢?那么在这个地方,那么我有一个block的一个源码,Block源码我现在来打开,打开之后呢,我在这里面做了一个操作。那么大家可以看到我当前在慢里面,那么写了一个block是吧,Block里面是不是引用了我的一个self,然后呢,我同时在当前这个工程里面通过脚本的形式,那么在这个地方我有一个脚本,通过这个脚本的形式呢?那么通过这个叉C文件可以去控制。
07:16
我当前那个脚本执行和输出的一个内容,那么什么意思呢?我给大家举个例子。那么此时我的工程变成了什么呢?那么在这个地方,那么有一个脚本,这是我的插扣的,那么与此同时呢,在这个地方有一个脚本,那么我的插扣的可以通过这个脚本。把你要输出的内容那么重定位到一个你指定的位置,那比如说终端好,有的同学就不理解,老师为什么要这么做,我直接在插扣子里面配置脚本不香吗?为什么要这么做?我们知道在插扣的中去执行脚本的时候,它的输出结果在哪看。有没有同学知道?我在这个地方执行脚本的时候,我执行这个脚本的输出结果在哪看。
08:04
在哪看?是不是我要打开当前的一个building,在这里面才能查看到我脚本执行的信息吧?这块能不能理解,我是不是在这个地方才能查看到脚本执行的信息吧。那么所以说我为了让脚本执行的信息更清晰,那我可不可以把它重新定位,定位到我当前的终端上呢?是不是当然是可以的,那么所以我来到这个地方,那么我直接把它定位到我当前终端上,我来到这个地方,我来一个TT,那么获取当前终端的这个标识符,哎,把它拷贝一下,放到这个地方,放到这个地方之后呢,我们来看一下。我现在执行的这个命令,那么首先第一命令使我们sc root block这个目录,那么实际上干什么呢?就是让当前的需要环境进入到我block t这个目录,然后呢,在这个目录里面通过我们的叉c wrong去执行我们可的一个命令。
09:04
把我们OC的源码,哎,我们的慢点M去转化成我们一个C加加来看一下底层的一个结构,好,那么这一步执行完毕之后呢,那么第三步。第三步。我们把这个生成的一个C加加文件打开,最后再从当前的block t里面,哎跳出去,好,那么这个地方就牵扯了一个一点是什么,那么我们在插扣的去执行脚本的时候,脚本的时候。那么它默认的这个路径是什么呢?默认的这个路径是我们当前的这个src这个路径,所以说我们要进行一个po出去,那么接下来我们卡门的加B进行编译,那么直接执行我这脚本,我大家看一下现在报什么错啊。但不能做。哦,他报什么呢。报我这里面一些错是吧。报我这里面的这个错误,来看一下把它怎么来视角。
10:05
报我的,可de错。Umbrella结构体。Include file from type。没有system放我来看一下,我来看一下这个为什么会出现这个问题,来用一下咱们当前这个资料里面试一下。会不会有这个问题?建议一下看一下。这个现在都是失败了。那就是我更新之后的这个wrong time wrong time,哎,它是有问题的,哎没有关系,那么更新之后的这wrong time有问题,那么大家可以关注一下我们逻辑教育,我们逻辑教育马上就会放出最新的一个labor closer的一个编译,那么首先第一点我们先来看一下,哎,当前的这个74里面,哎之前的这个block,那么生成的这个。我们这个结构体,那么到底是怎么样的?我首先来打开,进入到我们当前的这个blog t这个目录。
11:01
我们在这里面,我有一个提前编译好的一个C加加文件。那么我们首先来看一下这个CR文件,说不影响我们来看这个东西。那么首先第一点我们可以看到,那么在这个地方呢,实际上就是我的那个block编译出来的一个内容啊,我上一句上一节课讲的block编译出来内容,你看前面是不是通过杠杠week进行修饰,那么后面是我们的block,那么它现在是什么呢?它现在指向了一个慢block employment0。这么一个我们的一个函数的一个指针,那么这个函数的指针是一个什么呢?我们来看一下。那么这个函数的指针是不是一个结构体啊,并且大家可以很清楚的来看到里面是不是有一个ISA,是不是指向了一个take block,那所以说我们的block底层为什么是一个对象,是不是它里面也有sa,然后呢,这个地方还有一个PDRR,那么这个function PR指向了这个FP,那么这个FP是什么?那么就是。你写在。
12:00
你现在。写在。代码。快。里的。代码。那么什么意思呢?我们写在block代码块的这个代码,我们写在这里面代码,那么被我们的一个C加加底层转变成了什么呢?转变了一个静态函数,好,那么在这个地方我要问一下大家。静态函数是局部符号,是本地符号还是全局符号?Static修饰的一个静态变量是全局符号还是本地符号?来考一下大家。有没有同学知道?他这个修饰的变量。也就是说,出了本文件之后,我其他的文件能不能访问到这个函数?来,给大家五秒钟的时间,来五四。三。二。一还有没有其他同学,是不是static修饰的变量,它是一个本地符号吧,对不对?我们当我们通过编译程序之后,我们通过是不是会把这个static修饰变量的符号给它干掉,对不对?好,那么现在我们知道那么block底层,那么它整个是一个结构体,我们知道它里面有ISA,有一个函数指针,那么专门保存着我们写在block代码块里面代码,那么通过这两点,那么我通过一个事例给大家再来加深一下印象。
13:30
那么首先第一点我们判到我们这个self的多,那么self的我们之前验证了它是不是一个格global block,那么如何去判断block block那个类型呢?那么在这个地方我就不卖关子了,我直接给大家来看我们总结出来的,哎,派D老师给大家总结出来的判断block类型的一个条件,那么首先第一点如何判断lo网,那么在lo内部不使用外变量,或者只使用静态变量和全局变量。
14:00
那它是我们的global block,那么也就意味什么呢?我们self的虽然你用copy来修饰,但是你没有使用任何的局部变量吧,和我们的OC的属性吧,所以说它是一个global block。那么什么时候的lo呢?那么他俩要成为stick和lo,那么它在block的内部必须使用局部变量或者OC的属性,但是呢,Stick block不能赋制给强引用或者copy修饰。那么所以我们现在就能判断出来了,首先第一点我们要判断一个block的类型,我们是不是先要看block内部有没有使用变量啊。对不对。如果说他使用了静态变量或者全局变量,那么它肯定是格劳保,那么如果不是这两种变量,那么是不是只能从malo和stick里面去找啊?对不对?好,那么我们就着这两点,我们来看一下我当前在这个touch begin,那么我写了一个block,那么这个block是用杠杠week修饰的一个week block,那么请问按照刚才我们所说的这个判断条件,这是一个什么类型的block?
15:11
来,我把这个地方拷过来。什么类型的布BLOCK1格老二麦LO3。什么类型的?好,这位同学说是三好,刘成同学也说是三,还有没有其他同学?于杰说是二,还有没有?那么就我们来分析,那么首先第一点我们先来看这个block内部使用的这个变量,那么它使用的这个A是不是我定义在这个方法里面的一个局部变量,临时变量。那么所以说我们是不是只能从malo和stick里面去找,然后呢,并且我看到了前面是不是用杠杠week来修饰的,那么杠杠week也就意味着我当前的这个block是不是没有被强引用,你看它也提示我是不是你用week形式,那么所以说这应该是一个take block take block。
16:04
好,那么既然是一个stick block,我来到这个地方,我来打一个断点来卡的价格来运行。下来运行。点击。我之后来我点击点击之后我们来到这个地方,我来看一下当前的一个week block来往下走,是不是一个这个block对不对,好,那么接着我们往下来看,那么我们知道从我们刚才去分析block的这个结构体,我们得出了一个什么结论?我们知道ST。我们知道第1.block是不是有sa,第二点它是不是有一个方克声。PTR保存着PTR保存着我们写在block代码块里面代码,那么首先第一点,那么它既然底层是一个结构体,那么我是不是就可以来到这个地方,把我们的block转化成我们底层的这个结构体,那么怎么转化呢?那么首先第一点,我定一个跟底层相同类型的一个block的结构体,那么在这里面呢?哎,它也有IC指针,那么它同时也有一个function,那么这个就是它的一个函数指针。
17:18
那么接下来我通过咱们OC的一个桥接,那么把我们的block,那么转化成结构体这种形式,那么接下来再往下走,再往下走,我们可以看到,哎,这个block c已经出现了。这里面大家可以看到是不是整个的已经转化出来了,而且这个in work函数,那么我们可以打印一下。那么当前那个block in work,那么实际上就是它底层的那个函数指针,那么我现在来到这个地方,我再往下走,那么看到这个第三十三十三行代码,我干了一个什么事情?我们刚才说是不能赋制给强用的block,那么是我们一个stick block,那么现在我把这个block,那么赋制给了一个杠杠strong修饰的一个strong block,那么请问这个strong block是一个什么类型的block?
18:06
这个block是一个什么类型的block?这三种选一种。选一种来,这个才是我真正想问的一个问题。啊,L说是站上了,还有没有其他同学?来。五。这个strong block是一个什么类型的block?来五。三。好,嗯,那个同学说是对好,我们首先要我们来明白一点啊。就是当我们去执行这个语句代码的时候,我们知道block底层它是一个结构体。那么结构体我实际上执行到这一步,我是不是做了一个什么操作,在这个地方定义了一个strong block的这么。
19:01
一个结构体,然后呢,他接收了我的一个。Week block那么这么一个结构体,那么请问我把week block这个结构体赋值给了strong block。结构体之后。那么strong block是不是拿到了week block结构体里面的所有的参数,我是不是把我的IC。赋值给了你啊。我把我的ISA复制给了你,那么请问你的ISA跟我是不是一样的?是不是一样的。来,大家回答,告诉我是不是一样的?是不是一样的,那么所以说我执行完了这一步,那么我的strong block,它是不是仍然是一个战胜的block,所以我往下走,往下走。啊,我这个地方是不是改了源码,改了源码之后,我再重新编一下,就他记住我当前编译的这个行号了。先点击点击点击之后我看往下走,往下走,走到这儿我们来的地方死状block是它仍然是一个stick block,仍然是一个step block,然后呢,我为了给大家验证,那么既然结构体里面是不block,结构体里面是不是都有一个in work这么一个函数指针啊。
20:18
那么如果说我把我的结构题里面的内容都复制给了你,所以说你是不是跟我是一样的,那么如果说你要是一样的,我把其中的一个改成是一个六。那你是不是也要变成一个六啊?那么它既然是一个new了,我再去访问的时候是不是就会报错,也就意味着我执行到这一句代码,它报错了,那么我们上面所说的结构体等于结构体是不是就是正确的?这个地方能不能听明白。能不能听明白?来,不能听明白,我给大家来演示一下,能不能听明白。
21:04
我给大家演示一下,结构体等于结构体赋值,这个能听明白是吧。那么也就因为什么呢?我是不是通过这个地方侧面的给大家验证,我把其中一个赋值给new,再去调用另外一个,那么另外一个也报错的话,那是不是就说明什么,说明你俩是一个,所以我往下走,往下走是不是报一个坏地址访问,为什么?因为我把其中的一个引work,那么变成是new是吧,另一个in work是不是也同样跟着是一个new。所以说那么当你对这样进行赋值的时候,它本质上是不是就是一个结构体赋值给另一个结构体啊,那么所以说这一块你听明白了没有听明白的同学给我扣一波六六好吧。这一块很重要,是不是很重要,你现在是不是就知道那block类型的一个判断,那么首先第一点你按照咱们的规则判断,第二点你明白结构体复制个结构体,那么你就哎整个的就能把这个地方捋清楚了,好那么我们现在弄明白这个之后呢,那么接下来我们再来看一点东西。
22:08
这个地方是我刚才突然想到的,额外给大家加的一点内容啊,那么这个内容是什么呢?那么首先第一点我们要明白lock的这个调用。当我通过这种方式调用和我ns log。N log100分号,然后呢,我们的一个。撞不了。好,我通过这种方式调用。那么我实际上调用的底层的block,它的类型是不一样的,那么这个地方要给大家引出一个概念,那么block,当我的block,那么作为我们OC。对象的时候,那么它是什么呢?它是它就是作为OC对象,它是以对象的形式形式存在的。以对象的形式存在的。那么当我们的lock那么直接去调用的时候,那么它调用的实际上当前调用的实际上是lock的底层。
23:06
D。层的函数。指针什么意思呢?我们现在来看一下,现在来看一下。我现在来的地方,我打一个断点啊,打一个断点,我把上面这个设置六给注释掉,注释掉之后我们卡门的价格来运行。来点击点击点击到这个地方,我往下走,往下走好,那么首先第一点我打印当前的一个。Week克补到一个地址是不是零,是不是1004BF30B02,那么这个地址,哎,如果说你平常去研究这个马克马克欧比较多的话,你一眼就能认出来这个地址是什么地址。以100开头,然后呢,是64位的一个地址,那么它肯定是一个什么,是不是在我当前可执行文件里面去吧。这地方能不能理解?那么怎么给大家验证这个东西呢?
24:00
我们把这个地址拷贝一下,那么我们使用一个LDB的一个插件,那么这个插件叫一个什么呢?叫一个一个address。把这个地址拼上,拼上之后我们回车,那么大家可以看到当前这个地址它所在的空间是什么呢?杠杠钻杠杠tax session。杠杠T钻杠杠T3,我们知道它是不是在我们当前的mark欧中啊。然后呢,我再给大家就是说验证一下,那么首先第一点这个插件是怎么来使用,我们知道平常我们使用LDB的插件的话,哎,或者命令的话,如果说你不知道如何来使用这个命令的话,你怎么去查看它的一个help命令,查看它的一个。内部的那个演示的命令是什么?有没有同学知道是不是我通过help这个命令,比方说我们查看我们的po。你就可以知道po本质上是我们的expression-O杠杠的一个缩写,那么我们同样可以查看一下是不是我K这个命令,那么K这个命令是一个什么呢?哎,是我自己编写的一个。
25:01
我们的LDB的插件专门来查看地址所在的空间的。我们现在可以看到我直接去访问我的week block,那么这个week block的地址,它是不是在我们ma中啊?那么但是呢,我来到一个地方,我nslo我的block,你看见没有,现在打印出来这个mylolo的它的地址是什么,是不是零叉6006B6C10啊。为什么这两个地址不一样?我只是是不是打印了一下,和直接去访问为什么不一样,那么就是我上面这个规则,那么我们的block作为OC对象的时候,那么它就是以OC对象形式存在的,比方说我现在进行打印,是不是把strong block作为OC的对象?那么作为OC的对象,它会手动去,它会自动去拷贝到咱们那个堆上,你满足了。咱们成为melo和blog的条件,它会自动拷贝到这个堆上,那么所以说它打印出来那个地址,那么就是不一样,那么当你这样直接去调用的时候,你实际上调用的是它底层的这个方程PDR。
26:09
能不能理解,能理解的同学给我扣个一,能不能理解,给大家额外加了一点内容啊,如果说你探索这个block的时候。Block的说,哎。你发现这个问题,为什么我打印出来后,我直接去。访问这个指针为什么不一样?那么就是因为你这样直接调用访问的还是函数指针,当它作为对象的时候,那么它访问的是底层拷贝到拷贝上去的那个结构体啊。好,那么刚才有同学说,那么是怎么来拷贝的呢?那么首先第一点我们来看一下。那么刚才我们把这个地方是否block-in work置为六,我们知道在这个地方实际上发生的是不是我们的block的结构体,等于我们的一个结构体。那么现在我来干一个操作,我来到地方,我调用一个copy函数,是不是你你block不是OC的对象,我调用copy之后,那么请问我这样来执行还会不会报错?
27:06
还会不会报错?汇报错的同学给我扣个一。还会不会报错?还会不会报错好?不会,还有没有其他同学?为什么不会呢?因为首先第一点我们知道,那么补lock它进行拷贝的时候,或者说它是从什么地方拷贝到我们的堆上的。他是不是从站上。站上。拷贝到我的堆上了,是不是从站上拷贝到我的对上了,哎,我的站呢,是不是从站上拷贝到我的对上,所以说我当前这个胃口block是不是正好是一个战胜的block。然后呢,我拷贝了之后,是不是正好会把它拷贝到这个堆上,我们现在直接来看一下,哎,是不是这样的,那么我拷贝到堆上之后,那么也就意味着什么,我当前站上的block和堆上的block是不是两个block。
28:07
这地方能不能听明白。我站上的block和堆上的block是两个block了,我拷贝了之后。对不对,因为你拷贝到堆上了嘛,那么所以说我现在再去运行的话,你把这个引work置为new是不是就不会报错了,我现在点击点击来到地方,我们往下走往下走往下走往下走是不是不会报错了,然后往下走是不是正常的打印出来了,好那么现在就是什么呢?哎,Block到底是如何来拷贝的,那么这个是我们现在要弄明白的一个问题。Strong改成杠杠week,好,哎,这位同学问的非常好,我现在改成杠杠。请问。会不会报错?会不会报错?小眼静说,不会,还有没有其他同学?哎,我非常好,我觉得这位L同学问的非常好,L同学你再说一下会不会。
29:11
为什么不会,是不是结构体等于结构体,我当前的strong block是不是等于你的block copy之后的是不是两个结构体啊,所以说我现在卡的价格来运行。我先点击我点击点击到这的时候,我往下走,往下走我也不知道啊,往下走,哎。哎,报错了,报错之后我们来看一下为什么会报错啊。来这个地方看一下啊。一个杠杠。为不让我们来看下为什么会报错啊?这把我惊着了呢,怎么。来看一下当前的这个block啊,一个strong。呃,我等于block的一个copy。然后呢,A block的等于这个。
30:01
那我把这个关掉就会了。再往下走,往下走。哎,现在也也会报错,为什么会报错呢。现在不至为六也会报错。就看看我改了啥东西吗?为什么会报错啊,报错我strong strong block是一个new。是一个六,你看到没有。被释放。Week,不。撞了。哎,我这样写不行啊,我们来探索一下好不好,哎,这位同学说的非常好,我来探索一下好不好,那首先第一点,那么既然你当前我不是这样写的吗?我换一种写法啊,我当前是不是还是把它转化成我们的block,我现在换一种写法,我通过一个ID。ID一个杠杠杠week,我strong,不,我把它放到最前面,我现在这样写啊,这样写。
31:00
然后来到地方。等于我们的一个。Block,一个copy。这个block copy,然后把它关掉,关掉之后呢。我现在我。再这样来跑一下。Block的coffee。然后我把它再去转化一下喽。等于我的一个。撞不了。这样来转一下呢。把它作为这个OC的对象来。我们家。再往下走。哦,那他确实释放了,你看我的strong block是不是怎么转,它也是自为六了。比如说这个地方没有强引用。没有强引用,它自动就被咱们lo的那个奥,包括那个啥给回收了。
32:01
对不对,你看我现在通过杠杆壳没有强引用它,它自动就被回收了。对对,我现在,呃。那么这样的话,那么他就可以了。他有一次强引用我点击我现在再来点击我现在往下走。现在是不是就可以了。为什么?因为在这个地方,我是不是有了一个强引用啊。然后呢,我再来到这个地方进行赋值的时候,它是不是就不会销毁了。能不能理解我们刚才是不是直接杠刚问的话,那么当我去执行完了这个copy之后,返回的这个堆对象是不并没有任何的强引用吧,然后呢,我一步一步往下走的时候,是不是来到这个地方都没有强引用,然后是不是来到这儿的时候,我的这个对象是不是已经被释放了?那么所以说我把上面的这个杠杠位去掉,那么也就意味什么说在这个地方产生了这个强引用。所以说我是不是来到这儿的时候,是不是才去进行一个。
33:00
回收啊。堆上的不是出了作用域才去释放吗?我我我也在想了,他为什么来到这个地方直接就回收了。他为什么来,他为什么执行完这个剧之后直接就回收了呢?我也在想了,我回去看一下吧,好吧,回去看一下为什么会执行完这一句直接就回收了,因为按道理哈,我们来看,我们来做一个操作啊,你比方说。我杠杠胃口。一个NS,我不在乎一个星O。或C等于我们的一个。NN,我在。好,我来了就跑。来,你好,我再来一个ns log。来一。我们来看一下我当前这个OGC这个对象有没有被释放啊,有没有被释放。后面release after。Will be released。可能他底层的一个wrong time的一个逻辑了。
34:04
你看他是不是杠杠未可没有强引用的对象是不是在我们OC中,它底下是不是立即就被释放了,是不是立马被释放了。对不对,所以说从侧面验证了我们的block确实在我们OC中,作为对象,他走的也是我们OC对象的那一层逻辑啊。这地方能不能理解?当然在底层的一些具体的实现,那么就可能要底层去探索一下,哎,比方说我们可以看到之前的转化成C加加之后的这个代码。转化成C之后的代码,你比方说他通过这个O是吧,来到这个runtime得要好好去探索一下了,对吧。然后呢,那么这是我们讲的这个,哎,Block结构体相关的,那起码讲到现在,那么这个block结构体等于结构体这个地方大家听明白了没有听明白的同学给我扣个一。这block结构体等于结构体,大家听明白没有?好吧,那么接下来什么呢?我们来讲一下我们的block拷贝,那么在讲这个block拷贝之前呢,那么首先给大家推荐一下咱们今天这个资料,那么今天这个资料,那么第一点我给大家贴心的去准备了这个脚本,那么这个脚本我里面是有注释的,那么你就可以像cat老师这样,Cat老师这样,那么干一个什么事情呢?
35:20
在你当前的工程里面,把你当前工程执行的这个脚本命令执行,哎,不是这个。哎,我的那个脚本呢,啊大家对吧。把我当前工程你执行的这个脚本命令,那么同重新去定位到。重新去定位到输出的那个内容,重新定位到我当前的终端上,那么这个脚本今天给大家提供了,大家回去自己来尝试一下,并且呢,我里面有一个非常详细的一个注释。那么第二点就是什么呢?第二点就是关于这个LDB的这个插件,那么这个插件本体我也给大家提供了,它本身就是一个动态库,并且这个我还给大家提供了这个LDB隐匿的这个文件,这个文件是干什么呢?这个文件就是当我的工程去执行起来的时候,你可以去预先去加载一些LDB的一个命令。
36:15
那么关于这个东西怎么来使用,我也给大家提供了这个详细的一个文档,那么这是我们的第二份资料么?第三份资料是什么呢?就是咱们今天上课的这个圆满,那么有的同学说,哎,我想要去探索一下这个堆栈,哎,老师你上课讲的太快了,怎么办?那么第一点你可以拿到今天的一个录播视频,那第二点我把今天上课的这个源码也提供给大家了,大家回去可以按照我上面的这些一步一步的去探索一下,诶结构体等于结构体你可能今天记住了,那么你再去看一下,诶,为什么是这样来操作的。那么所以说今天一共给大家提供咱们这三份资料,那么有需要的同学加一下咱们的助理老师,那么与此同时,我再给大家预告一下,咱们今天不要早走啊。
37:02
我一会儿在课程结束的时候,我会给大家讲解咱们酷帕一个源码的一个调试好不好。1123。那么首先第一点我们要去明白一下那个捕捞补货变量,它到底是怎么补货的。我们来看一下当前这个源码啊。我们从转转出来的C加加这个码啊,那么在这个地方我们可以看到,在慢函数里面,我们定义了一个的一个变量叫一个,然后呢,同时什么呢。我是不是又把这个self。负只给了一个咱们的一个week self对不对,然后呢,这个week self是不是被我当前的这个补捞捕获进来了,是作为他的成员变量捕获进去了。好,我们现在注意一点啊,大家注意看我前面是不是一个杠杠死状来修饰的。那么当他被捕获进去的时候,哎,你发现他前面是不是也是一个杠杠,Strong?那么所以说当你捕获这个变量的时候。
38:04
那么此时在这个地方是不是就会产生强引用啊,那么我们换句话来讲,那么他现在是用的strong,而如果说我把它改成杠杠wi呢。那么也就意味着什么?我补block捕获变量的时候,是不是此时也变成一个杠杠week?这块能理解吗?这块能理解吗?能理解的同学给我扣个一,此时也变成了一个杠杠weak。好,你能理解是吧,能理解之后,那么我反过头来再来看,哎,我现在这个week o,我变成一个杠杠week式的。那么也就意味着什么,也就意味什么,我当前这个week o被我的这个strong block捕获进去,哎,作为他的成员变量的时候,它是不是也是一个杠杠。Week修饰的。那么请问在这一步,它有没有产生这个。
39:01
强引用。那包括它拷贝到这个堆上,有没有产生强引用。有没有产生强饮用?有没有吗?那么接下来我们再来看第二个,那么站上的这个补lo,哎,我跟大家说站上的这个补lo,那么同样的它补货这个变量的时候,他补货进去,是不是他也按照这个规则,遇弱补弱,遇强不强,那么所以说他补货进去的时候是不是也是一个。杠杠未可修斯的。杠杠未可修饰,那么它既然是一个杠杠未可修饰的,那么战胜了这个block,有对它产生强引用吗?哎,我战胜了block,我有拷贝到这个堆上吗?
40:03
我有没有没有吧,那所以说我砍完的价再来运行一下。再来运行一下。我点击。是不是一个122啊,为什么,因为你在这个地方,你不是有了一个从站拷贝到堆上这么一个操作吗。是不是,所以说你的是不是从一。来到这个地方就变成了一个二啊。能不能理解?但是呢,我战胜的block是不是并没有拷贝了,所以说我是不是仍然维持着这个二。所以本质上是不是就是我们这。规则遇强。则强,遇弱则弱。能理解吧?能理解的同学,那么接下来我们再来看一个面试题,再来看一个面试题,我把这个地方注释掉啊。能不能理解嘛。没有关系嘛,没有不能理解,我再给大家带来演示嘛,我为什么今天给大家出这些面试题,是不是实际上就是来加深大家一个印象的嘛,对不对。
41:05
我做这这面题,我的作用是什么?就一遍一遍的,就是给大家加深一个印象嘛。不理解,怎么不理解呢?不理解,我再给大家讲一遍好不好?需要我再讲一遍的同学,给我扣个666。好,我今天我就跟大家拼了,我就今天给大家大家讲一遍好吧。好,那么第一点我们记住这个规则,那么捕捞捕获这个变量的时候,那么预弱补弱捕获。遇弱不弱。然后呢,遇强补强,那么什么意思呢。那么当你是一个杠杠未可修饰的时候,杠杠未可。当你是一个杠杠未可修饰的时候,那么我补货进去,我补货进去。那么它也是一个杠杠week来修饰,那么也就因为什么呢?我补货进去也是一个杠杠week来修饰我的return count。
42:04
有没有变化,有没有变化。有没有变化?这个没有啊,这个没有。好,那么什么呢?我杠杠死状来修饰的呢,哎,遇强补强那它就不一样了,对不对。一个杠杠状,遇强补强的就不一样了,那么我遇强补强再去补货的时候,那补货进去的它也是一个杠杠死状,哎,去引用的,那它的return count是不是就要进行一个加一了。好,我们按照这个原则,那么首先我们来看一下我当前这个ns object week o是不是被杠杠week来修饰的,那么也就意味着被我当前这个补了进行补货的时候,补货进去,它的引用技术有没有增加。有没有增加补货进去,有没有增加,是不是没有啊。
43:01
是不是没有,是不是一直到这个地方都没有吧,为什么,因为。遇弱不弱吧,那么他为什么引用技术变成了二呢?因为你这个是一个。堆上的block。他是不是要经历一个从战。拷贝到。我们微上的这么一个过程。堆上。对上这么一个过程吧。对不对,那么当他从站拷贝到堆上的时候,他同时是不是拷贝了我们。捕获的一个变量,哎在哪个地方呢?我们来看一下底层源码copy的时候,哎就是这一句,就是这一句。它会copy我当前补货的这个成员变量。捕获的是成员变量,所以说当这一句执行完毕之后,那么我当前的引用技术会变成二。能不能理解?
44:00
能不能理解?这个地方能理解吧。我看一下刚才那个有同学说不理解的。可以吧?好。哎,他咋他咋没有没有给我扣一。那那个那个同学呢,他没有给我扣一。啊,理解是吧,好理解就行,好,那接下来我们再往这个地方走,那么这个是不是是一个战胜的block,杠杠未可修饰的战胜的block,哎,战胜的block和堆上的block都去遵循这一个原则,对不对?那么战胜了block捕获一个杠杠week来修饰的时候,捕获进来是不是他也没有对他产生任何的强引用吧,所以到这一步。引用技术是不是一直是二啊,而且站上的block它是不是没有拷贝到对上。No拷贝到堆上,那么所以说它的引用技术应该是几。
45:01
是不是应该是一个。二吧。那么所以说我现在再给大家来执行一个什么呢?我来到这个week block,我调用一下。调用copy之后,那么请问我来到这个地方再去执行,哎,我再来电话我接收一下啊。接收一下什么呢。Copy之后。来一个。ID。来一个copy一个block,等于它这样来接收,是我现在copy了一下,然后呢,我把它又去转成一个。来个地方我把它转一下啊。转成我们的一个。Copy block,哎,我直接这样等于是不是就可以了。来,这样等于角。我现在调用这个copy block。用它copy block,请问这个地方还会输出这个二吗?还会输出吗?
46:00
它会输出解。来,我们来运行一下看的加。哎,咋没没没打印呢。我哦,我把这个电话删掉了。重新付一下。Block。来看我们的加来运行。那我点击。仍然是一个二。看一下啊,看一下为什么它仍然是一个二啊,我这样写了之后。首先第一点,我当前这个block,那么它肯定是一个。是一个对象的萝。背上了block。那我再去捕获他。他会再去重新去拷贝到这个堆上吗?他会重新去拷贝这个到这个对象吗?我来我来调一下。
47:04
应该是一个二。那也就意味着什么,也就意味着什么,我当前这个变量是不是再堆上了。再堆上。我当前这个变量,我的这个week block,我的这个。我哪个哪个变量了。我当前这个变量,当前这个O这个变量。他再堆上了。他被拷贝到这个堆上之后,他就。不会再去触发这一步操作了。我们来试验一下啊,试验一下我把这个杠杠week给它去掉,去掉之后。去掉之后,如果说还是打印出来的是一个二。那也就意味着他执行完这一步,拷贝到堆上之后,他就不会再去copy了。能不能理解?那我卡加下来运行一下,能不能理解吗。我们来探索嘛,对吧。
48:01
我现在来。现在来我来现在来点击,点击之后,哎,来到对方,我现在。它是不是仍然是一个二,那说明了什么?说明我们被block捕获的这个变量,它拷贝到堆上之后,是不是接下来就不会再去copy了。能不能这样理解?可不可以大家看一下。是不是可以这样来理解,为什么我现在是不是也是一个。站上了补,我现在是这个是不是一个从站上拷贝到堆上了,这个是不是也是从站上拷贝到堆上了,那也就意味着我的补获那个变量是不是拷贝到堆上之后,我下一次是不是不用再去copy一次了,哎是不是只copy一次,哎是不是咱们今天,哎就是这个课是不是又探索出了一个新的知识点,哎,你们不应该给我扣一波666吗?对吧,看老师不怕不怕翻车,我们只要有例子是不是就能去验证这个东西啊,对不对,不怕翻车,只要有例子就能去验证,好吧,那接下来我们再往后讲啊,再往后讲,那么这是我们讲的他引用技术,那么接下来我们来再来看一个面试题啊。
49:08
哎,今天这个block面题我就非给他给他讲明白不行。那么这个面试题是一个什么呢?哎,这个面试题我们接下来再来看啊。Copy的应该是那个block,对呀,他从站copy到我们的堆上之后,他应该去触发block的copy嘛,那他只要去触发block copy,那他应该正常去走block copy那个逻辑嘛。那么这一块的话,哎,你可能就需要把这个函数里面这个内容来探索一下。探索一下。然后呢,我们接着往下走啊,那么首先第一点,那么现在是一个杠杠weak修饰的一个week block,那么但是这个block内部是不是捕获了咱们的局部变量。那么他既然捕获了局部变量,那么所以说哎,它是一个什么。是不是我们的一个lo没有问题吧。那么block呢?接下来我干了一个什么操作呢?
50:01
我接下来干了这么一个操作,那么首先第一点。啊,这个地方没有用到的。我来一个dispatch after,那么这个dispatch after延了三秒去执行我的这个block,请问我这样写会不会有问题?这样写会不会有问题?哎,所以说你们今天得拿到我这个代码,你们回去好好来研究一下。说看到老师不坑你们对吧。我这样写会不会有问题?好,这位同学说是会,还有没有其他同学?然后他会的点在哪。是不是还是跟我们站上的这个变量被系统回收和释放,哎,创建和释放有关系啊,我们知道站上的这个block它本身它也是一个占变量,那么站上的变量也就意味着什么,出了当前的这个方法函数之后,那么这个变量它会被系统回收,那么也就意味着我延迟三秒钟之后再去访问这个变量,它是不是会报一个怪地址啊,那么所以我来到地方,哎,我来写一下,写一下之后访问的加热来运行。
51:17
我现在点击。二。哎,是不是直接报一个坏地址访问,那么为了给大家再去加深这个站上的变量,它的一个生存的一个时间,生存一个空间,那么怎么办呢?我们通过融入。我通过run入让我当前的这个方法,那么执行到134行的时候,让它延迟三秒钟再去往下执行,那么什么意思呢?我通过让我当前的代码在这个地方,诶。Lock住,阻塞住,让他三秒钟之后再去往下。再去往下执行。
52:00
你明白我意思吗?那么如果说三秒钟之后往下执行,那么同时我的dispatch after也掉到了。那么意味着什么?我的block是不是不会报这个外地去访问啊?所以我现在卡的价格来运行。我现在点击,哎,是不是三秒按123。哎,正常的是不是打印出来了,所以关于这个站上的变量,哎,它的一个创建和回收这个作用域能不能理解。应该能理解了,我反复再给大家加深个印象,能理解了吧?那么也就意味着什么啊,我现在如果把这个杠杠week来去掉。我这样还会报错吗?我把刚刚未来去掉,还会报错吗?把刚刚未来去掉,还会报错吗?好。你们刚才说理解,我觉得你们都没有理解,没有理解的点在哪呢?
53:00
你记住没有,Block在OC中它是不是作为一个对象,那么作为一个对象,那么你前面是不是杠杠杠杠strong,那么也就意味着我的lock是不是把你补货的时候,是不是也要遵循这一个原则,哪个原则?哎,我那个面提呢。哎,我刚才面试题了啊,就在这。遵循一个什么原则,是不是遇弱补弱,遇强补强呀。那么也就意味着,当我把这个杠杠胃去掉的时候,它现在是不是变成了一个?对象啊,前面默认是一个杠杠死状的一个对象了。杠杠死撞了一个对象了,那么也就因为什么杠杠死撞一个对象,被我当前这个block捕获进去的话,它是不是也是一个强饮用啊?那么也就意味着我这个block的生命周期有多长?
54:01
是不是你的dispatch after执行完毕之后才会去释放?他捕获的block。是不是从这个地方去解释更好来理解一下。你明白我意思吗?明白的同学给我扣个一。啊。好,那么讲到这个地方,那么我还欠大家一个什么呢?第一点,哎,咱们的一个week strong还没有给大家讲,那么还有一个什么呢?还有一个,哎,咱们的一个咖。不卡po子的一个源码调试,没有给大家讲。圆满调整,那么来到这个地方,那么我首先先给大家来总结一下,我们现在讲的一个内容,我们刚才讲了是不是第一点,哎,Block的一个。的一个堆栈。那么堆战最重要的一点,我们是不是理解了一个遇弱补弱,遇强补强呀,对不对,然后呢,我们是不是进而去理解了咱们block,哎,它的一个底层,它是一个结构体。
55:05
结构体,那么所以说我们对一个block进行赋值的时候,本质上是一个什么?是不是结构体等于一个结构体啊?我讲到这个地方,哎,咱们觉得今天咱们block讲的有没有意思,觉得讲的有意思的同学,哎,给我扣个六六。大家还想不想接着往下听。咱们接着往下听。好。那么在这个地方呢,哎,我们就顺着咱们目前讲的这个内容,那么给大家来推荐一套咱们逻辑教育,哎,最新推出的一个is的一个高级的一个系统课程。那么为什么要给大家突然推荐这个课程呢?因为很简单,咱们今天课堂上讲的那个内容,那么实际上就是咱们逻辑教育V14I大师班级里面,咱们不唠相关的那个内容,哎,大家不要担心,马上我会给大家把这个两点,哎,咱们马上来讲解起来,哎,请允许现在我给大家介绍一下咱们这个课程。
56:11
那么lo这一块,那么大家可以看到它其实牵扯的内容非常非常广,那么这一块我们是不是可以对这个ma沃,对我们的内存啊,包括那么本身的weak strong,它其实是对什么的理解。是不是对我们的一个runtime的一个理解,所以说block是最能串气咱们is开发中底层原理的一个知识点。那么然后呢,我们来看一下这个大师班级里面到底有哪些内容,那么第一块就是咱们那个run time底层对象的一个分析,为什么要分析对象,我们今天从lo就看出来了,哎,我们知道一个对象存在的一个空间,以及它底层的一个探索,哎,他lo引,哎,就是像我今天一开始出的那个问题。我为什么加了一个杠杠week之后,那么他的立马会变成一个new?
57:01
对吧,为什么我不加杠week之后,哎,我这个对象就能实际存在呢?那么我们是不是就要研究一下咱们wrongtime底层,哎,对alo in到底是怎么实现的,以及我们杠杠week这个关键字是怎么来实现的?那么同时呢,你研究完对象之后,你是不是要研究这个类,哎,为什么要研究类,因为我们知道我们从ma o中把我们OC动态性的那个东西读取出来,那本质上是不是就是去转成这两个结构体啊。那么这两个结构体,哎,相关的一些分析,是不是也是面试中经常问到的一个点,哎。你看我们今天是不是分析了一下补捞结构体,我们之间就能收获这么多,就它的IA,它的方式PDR,它怎么去捕获变量了,那么我们去分析我们真正的一个OC的对象的类本质,那么我们是不是就能对OC语言,还包括对我们的SW的语言就掌握的更加清晰呢?那么同时我们再去看一下,哎,咱们对象中的这个属性,那么属性是怎么来加载的呢?哎,包括我们在这个地方,我通过copy修饰的这个属性,那么到底在底层,哎怎么去进行给我一个转换呢?哎,包括这个实力变量属性的一个对比,哎红是怎么进行预变异呢?
58:19
看完了属性之后,我们再来看这个方法,哎,Opc sent怎么进行一个消息发送,我能不能耗它,耗它达到一个无买点的一个操作呢?哎,整个消息的一个发送机制是不是,它是怎么样的呢?哎,是怎么一步一步的去找到我们的原类,找到我们的IA最顶层的那个结构体呢?那包括我们的协议,哎,编译加载分类,分类这一块是不是跟我们的动态库,哎跟我们的静态库是不是一定要结合起来,那为什么要跟我们的动态库结合起来呢?因为动态库它是不是经历了那个点O链接的一个过程,那么你的点O如果说不指定去加载这个分类的话,那么也就意味着你的动态库里面是不是就没有这个分类的一个代码,那么再去运行的时候,哎,你的动态库是不是就报会报安范。
59:10
咱们的一个。不是按申报啊,是找不到方法那个错误,那么这个地方我们就来来看一下,哎,为什么分类是动态创建的哎,以及它的一个底层的一个实现,哎,Load和引匿少。那么来到这之后呢,我们整个的一个wrong time的底层已经探索完了,哎,现在我们来看一下应用到底是怎么来加载了啊,我的DLD如何去加载我们的应用,以及哎,我们的慢函数,我们的慢函数,哎,你看wrongtime。注册回调函数run time是不是它也是一个动态库啊,它是由DYLD去调用我们当前可执行文件的时候,是不是由由一个注册函数是不是动态的去注册我们的状态。那么然后呢,再有一点是什么呢?哎,这个地方又牵扯出来了,我们平常常见的这个优化。冷启动热启动是不是,冷启动是什么,我第一次启动APP,那么主要影响的是什么呢?我们动态库,那动态库是由谁来加载呢?哎,我们的DYLD,那所以说整个学到这儿,那么都是咱们底层的一个。
60:13
习,那么再来到这之后呢,再来看一下咱们核心编程探索篇,那么这一块整个的是把我们上面所有学习的咱们的底层原理,咱们的哎,一些原理原呃,原理方法是吧,把它应用到我们的一个实际开发,怎样去进行这个启动优化,哎,怎么优化我们的启动,怎么去应优化我们的一个应用瘦身,怎么去进行我们内存的一些优化,怎么进行我们的界面优化和架构优化,这个课程是老师讲的吗?哎,这个课程是咱们逻辑教育的金牌讲师库CI老师给大家讲。那么咱们微14课程不光有大师班,那么还有咱们的flat高级进阶班,那么Fla高级进阶班,哎,是按照咱们is开发现在的一个思维方式,包括咱们is开发,哎对这个跨平台的一个要求,那么给大家设计这个课程,那么里面重点讲解的你像咱们Fla的一个文本渲染。
61:06
Flat如何实现像我们ISI微博那种开包V的一个无限滚动延迟加载,那包括flat原理的一个探索,那么这是咱们Fla高级经验班,那么还有什么呢?还有咱们Swift的高级经验班,那么这个是针对咱们Swift底层。进行讲解的,你比方说常见的面试题,哎,Glass与结构体的一个区别,哎什么时候该用glass,什么时候该用结构体,以及是吧,我们的let和哇修饰变量的一个区别,哎指针的一个实战是吧,我们学习完底层之后,我们SW既然是那么灵活的语言,我们为什么不可以自己去实际去创建去优化呢?哎,这是哎咱们的所谓的高级纪念班,那么咱们最后一个微14的课程是数据结构与算法课程,哎这个数据结构与算法课程主要是针对哎目前,哎咱们现在有些同学,那么你只知其一不知其二,为什么呢?你比方说咱们的杠杠未课修饰的变量是不是放到底层的一个弱引用表,是不是全局的,它是以一个什么形式存储的,是不是?
62:08
一个双向链表,哎,那为什么要以双向链表呢?哎来这就是数据结构与算法了,那比方说咱们平常,哎,可能经常见到的一个堆排序。等等等等,那在咱们这个课程里面都会给大家深入讲解,那么再去配合,哎,现在开发的一个面试题相关,那么针对面试题去帮助大家去理解这个数据结构算法,那么真正的去帮助大家把这个东西应用到开发,那么同时能去。应对到咱们大厂的一个面试题,好,那么这个课程,那么大家想要了解的话,哎,包括你也想来看一下底层原理这一块,包括我在开发中可以把底层原理应用到哪些实际开发,那么大家可以加一下咱们今天的一个客服老师。来,整个来获取一下咱们V14的课程大纲。没看清是吧,哎,发个图瞅瞅,哎,加一下咱们的一个客服老师,整个的来看一下这个课程大纲,看一下这个课程大纲,哎,具体要学习多久,咱们整个的一个课程是六个月的一个学习时。
我来说两句