|
|
根据其提示修改http.postBuffer,改大一点就行了git config http.postBuffer 524288000
第二个问题:
|
|
修改config: git config http.sslVersion tlsv1.3
gogogo
|
|
根据其提示修改http.postBuffer,改大一点就行了git config http.postBuffer 524288000
第二个问题:
|
|
修改config: git config http.sslVersion tlsv1.3
如何将一个CMSampleBuffer转为一个UIImage呢?
|
|
这个方法只能在iOS9以上执行,而且我还遇到一个问题,连续调用VTCreateCGImageFromCVPixelBuffer 15次后,会将AVCaptureSession的video连接给断开,非常神奇 - -!,以至于老是卡主我的预览。
|
|
目前用的就是这个。
这是第三方库SRRecorder中使用的方法,不过还是需要pixeltype为kCVPixelFormatType_32BGRA才行。
|
|
|
|
在https://github.com/nabla-c0d3/ssl-kill-switch2下载工程。
途中遇到报错:
执行
安装完成后再执行make package
就能得到生成的deb了
进入cydia,确保安装了
Debian Packager
Cydia Substrate
PreferenceLoader
拷贝deb到/usr/local/bin/下,执行
如果要卸载的话,执行:
安装完成后,设置中会新增一个ssl kill switcher2的选项,进去,打开它。
然后再用charles抓包,基本上能够抓取市面上的大部分的包。有一些比如微信使用了自己的mmtls协议,是没法查看具体请求内容的。
参见https://www.jianshu.com/p/91e0c22a6ea7
我们在编程中经常处理各种事件,各种事件也和我们的业务逻辑紧密相关,比如点击了这个btn,我该执行什么逻辑等等、我该用代理、通知、还是target-action来传递我们的事件、我该在main queue还是global queue上执行任务等等。在rxswift看来,无论是什么场景,这里面有一个不变的东西,那就是消息的生产、消息的发送、消息的处理、资源的销毁。
我们以前实际上是用业务逻辑去包裹了这一套东西。rxswift认为这样实际上是做反了,我们应该以消息的流动去包裹业务逻辑,而不应该用业务逻辑去包裹消息的流动。因为消息的流动是不变的,业务逻辑是变的,根据封装 变化的原则,我们用一个抽象的叫做Observable的东西来封装不同的业务逻辑。然后用Observerbal、Observer、disposable、scheduler等实现一套通用的消息处理机制。这样就能从各种代理、通知、target-action不同的消息处理方式中解放出来,使用同一的Observerable、Observer来实现。而且rx是一整套的,所以如果你切换到java,c++等其他语言,你也可以不用对每种语言都了解线程、传值、通知等,就能直接使用顶层的抽象。ok,按照这样的理解,我们来看看rxswift中的几个比较重要的类。
消息的流动是从消息的生成开始。而Observable就是代表这个抽象。不过呢,rxswift不止把消息生成的任务交给了Observable,还将消息发送的功能交给了Observable,也就是subscribe函数。
|
|
消息流动过程中消息的处理者。Observer就代表这个抽象。
|
|
如果调用了disposable的dispose方法,则代表了,任务已经完成或者取消执行,然后进行资源的清理。disposable有时会很复杂,因为他要清理资源,而我们的Observable可能是由多个Observable按照某种约定生成的,所以最终的disposable需要负责dispose所有的disposable。当然如果情况简单,可以创建一个简单的disposable。
|
|
提供了统一的方式让我们在不同线程执行任务。MainQueue, GloableQueue…
producer是实现了Observable协议的一个基类。他重写了subscribe方法,处理了isScheduleRequired的问题,然后将具体的消息发送交给了run方法。
|
|
读过一遍之后,我们可能会有这几个疑问:
要解释这个问题,我们的先了解什么是CurrentThreadScheduler ,他是拿来干啥的?
CurrentThreadScheduler抽象了在当前线程执行某个任务的这样一个功能。非常重要的一点是,他是一个Serail scheduler
。也就是说我是串行执行的,因为我们可能在其他不同线程上dispatch了一些任务到这个线程。那要怎么保证串行执行呢?恩,我们定义一个pthread_key 。如果当前线程有任务再执行,那么我们在当前的线程中设置一个specific存储这个key和value。任务执行完成后,我们清除这个标记。当有其他任务一起进来时,会先判断有没有这个key,有的话表示线程正在执行任务,其他任务会被放到一个Queue中缓存起来,在当前任务执行完成之后执行。所以isScheduleRequired
其实是一个防止并发的标记。我们来看看代码:
|
|
|
|
好了,现在我们知道Producer处理了通用情况,在当前线程执行任务,并且通过isScheduleRequired处理了并发的情况。
我的理解是用于取消。在subscribe过程中,我们可能创建许多的disposable,但是假如我们要取消,怎么办呢?没错,所有disposable都调用dispose就行啦。好的,那总有一个东西记录所有的disposable吧,没错,于是我们定义了SinkDisposable,他包裹了两个disposable。在取消时,调用sinkdisposable的dispose就行了,sinkdisposable又会去调用sink和subscribe返回的disposable的dispose。这样所有都释放完了,我们不用知道这个过程中生成了那些disposable。
|
|
|
|
subscription这个disposable,我们很好理解。subscribe方法就会返回一个disposable。这里的就是那个disposable。
sink是一个observer+cancelable组合成的disposable。我们从上面可以看到,subscribe方法将具体的消息发送交给了run方法。所以我们需要在run方法里实现类似于Observer.on()这样的代码。而Sink就是对这部分代码的封装。他们都有一些共同的特性,比如都需要一个Observer来执行on,需要一个cancelabl来取消,都需要一个方法来执行Observer.on方法。将这些通用的东西提取出来就是Sink类。
|
|
|
|
好了,现在来看看一个完整的例子,我们选简单的Just来分析下。Just只是简单的发送一个element而已。
|
|
|
|
|
|
|
|
|
|
好了,其实很多rxswift operater都是按照这样写法完成的,我们其实可以先不看他的实现,自己先按照这一套东西写一遍,再比对,可以加深我们对泛型的理解还有具体的实现。
在消息传递的线路中,我们可能会需要这样的一种中间节点。他从别的地方接收消息(也可能自己直接onEvent),然后将这个消息分发给其他多个Observer。相当于一个中间的消息转发装置。Subject就是对这样的节点的一个抽象。
由于他能接收消息,所以应该实现ObserverType协议。他又能将消息发送给其他多个Observer,所以他还必须是一个Observable 。同时他还能断开这个节点,所以他还需要是一个disposable,在dispos时移除所有observer。
|
|
还有其他几种subject,他们都是处理某些特殊情况,比如:如果我的observer是在事件流动的过程中加入的,那么我想加入后能够立即收到SUbject最后收到的那个消息,这就是BehaviorSubject
完成的工作。还有ReplaySubject和AsyncSubject,都比较简单。
Mirror用于获取任意类型的结构。
|
|
使用很简单,ok让我们看看他做了些什么
|
|
可以看到调用了Mirror(internalReflecting: subject)
进行初始化。
|
|
Ok,再来看看其中的几个函数:
|
|
|
|
|
|
|
|
他们都是调用call,并把我们需要mirror的value,以及value的type传入,最后调用个闭包之类的。
|
|
ok,从上可以看到,关键在于各种RelectionImple类的实现,我们找一个看看:
|
|
从上可以看出关键点在于我们的Meta信息,我们继续看下去:
|
|
|
|
|
|
|
|
我们编译时,会为每种类型生成他们的typemetadata。我们定义的每种类型都能找到他的typemetadata。反射就是从这些metadata中拿到成员变量数量,成员变量的offset等,然后根据这些信息,从我们传入的subject中获取到对应的value,然后组装成Mirror返回给我们。
在swift中,一个对象在概念上有三种refcount。strong和unowned存在inlineref字段中,weak存在sidetable的refcount中。
对象初始化时是没有side table的。在下面情况下会生成:
强引用和无主引用指向这个对象。
弱引用指向这个对象的side table(声明一个weak变量相当于定义了一个WeakRefrence对象,这个对象会持有一个WeakReferenceBits, WeakReferenceBits是通过sidetableentry初始化的,sidetableentry包含了引用对象的指针和引用计数,所以当strongRC为0时,对象可以通过HeapObject的ref找到sidetableentry,并把其中的对象指针设置为nil,这样弱引用访问拿到的都是nil)。
swift中每个对象都是一个HeapObject。下面是他的定义:
|
|
|
|
|
|
Live
(没有side table):
对象的refcounts被初始化为:strong 1, unowned 1 ,weak 1。
Strong varibale正常工作。
unowned variable正常工作。
没有weak variable。
如果你声明了一个weak variable,那么会添加side table,对象变成Live with side table状态。
当strong RC变为0了,会调用deinit(),然后对象状态变为DEINITING
。
Live
(有side table)
weak variable正常工作。
其他的和Live相同。
DEINITING
(没有side table)
deinit()正在进行。
强引用变量将不能使用。
使用unowned variable会引发swift_abortRetainUnowned() 错误。
unowned variable的赋值正常工作。
weak variable 不能使用。(因为没有side table就没有弱引用,所以也不存在使用弱引用变量)。
weak variable的赋值会存为nil。
当deinit()完成后,会调用swift_deallocObject 。swift_deallocObject 会调用canBeFreedNow() 来检查还有没有weak或者unowned references。如果canBeFreedNow返回yes,那么这个对象被free掉,对象变为DEAD
,否则,将减少无主引用,对象变为DEINITED
状态。
DEINITING
有side table
weak varibale为nil。canBeFreedNow 会一直返回false,所以这种情况不可能直接变为DEAD。
其他同上。
DEINITED
没有side table。
deinit()完成了,不过无主引用unowned references还存在。
Strong variable的操作(store和load)不可能发生。
Unowned varibale的store不可能发生。
Unowned varibale的load会报swift_abortRetainUnowned() 。
weak variable的操作不能执行。
如果unowned RC为0了,对象会被free掉,然后变为DEAD
DEINITED
有side table。
weak variable的load会返回nil。
Weak variable的store不可能发生。
当unowned RC为0时,对象被free掉。减少weak RC, 对象变为FREED。
其他的同上。
FREED
没有side table
不可能发生,因为FREED需要weak RC, 有weak RC就一定有side table。
FREED
有side table。
对象虽然free了,但是指向side table的weak references还存在。
strong variable的操作不可能发生。
unowned variable的操作不可能发生。
weak variable的load会返回nil。
Weak variable的store不可能发生。
当weak RC为0时,side table entry会free掉,对象变为DEAD
DEAD
对象和他的side table都释放了。
循环强引用,导致了strongRC永远都不会为0,所以对象永远也不会deinit,也就不会free,sidetable有的话也不会释放掉。
我们可以使用weak或者unowned来打破,那什么时候使用呢?其实根据weak和unowned的特性,我们就能知道:
ok,结论就是如果你非常确定引用的对象在使用期间一直存在的,那么就用unowned。
如果你不太确定或者对象就是可能在使用期间已经被释放掉了,那么使用weak。
结构体和元组当前共享相同的布局算法,在编译器实现中称为“通用”布局算法。算法如下:
比如:
|
|
参考https://academy.realm.io/posts/goto-mike-ash-exploring-swift-memory-layout/, 里面有一个探索内存的工具https://github.com/mikeash/memorydumper2。我们传一个变量给他,他能分析出这个是一个指针还是其他东西,并给出关系图谱,不过需要安装Graphviz。
class是引用类型,因此,我们定义一个变量拿到的是这个实例变量在内存中的引用。
|
|
那么p指向的实例对象的内存模式大概长什么样呢?
现在还看不懂,我们先介绍下swift源码中的一些数据结构。
swift中所有分配在堆上的东西都是一个HeapObject。我们看看HeapObject的定义:
|
|
HeapMetadata是类结构体的指针。
|
|
综上,我们看到HeapMetadata就是一个类结构体。代表这个实例的Class。HeapObject中的第一个变量
HeapMetadata const *metadata
就是一个指向Class对象的指针。
|
|
从上可以看出InlineRefCounts就是InlineRefCountBits,并提供了各种操作引用计数的方法。
|
|
从上可以看到,refCounts是一个RefCountBitsT类,类中有一个bits。如果没有sidetable的情况,那么引用计数会记录在这里面,如果有sidetable,那么包含的是HeapObjectSideTableEntry的指针。
|
|
再看看一开始的图:
E87b5600100000:是Class的地址。
02000000000000:是inlineref。引用计数,不过怎么都和看到的offset对不上😆。02那个是00000010,其中的1是代表unowned ref的数量,我们可以验证下:
|
|
上面有5个额外强引用,2个额外无主引用(总数为2+1,因为初始值为1),虽然不知道具体的offset规则,不过我们可以肯定,一定有一个1010和一个11子序列,代表5个额外强引用和3个无主引用:
可以看到06(00000110),其中11位无主引用数3,0a(00001010),其中101为额外强引用计数。
ok,我们在试试定义一个weak,让对象有sidetable(因为weak引用计数在sidetable的SideTableRefCountBits中)。
|
|
可以看到ref已经变味一个指针+flag。
这是Person这个Class中的信息,读取的信息描述也不是很清晰,我们大概可以认为他是一个特殊的vtable,混杂了一些oc类结构体中的一些信息。
|
|
这是放大的部分,128字节开始是sayHello函数,136字节开始是sayWorld函数,还有各种getter和setter等。
第8字节开始,也就数superclass,可以看到,我们定义的Person是SwiftObject的子类。SwiftObject是一个实现了NSObject协议的OC类。
在layout枚举时,ABI为了避免浪费空间,会从以下的5种策略中选择。
|
|
如果enum只有一个case,那么关联了什么data就怎么布局,如果没有关联,那么为empty(因为只有一个case不需要区分)。
|
|
如果所有case都没有关联data type,那么这就是一个c-like enum。enum布局就是一个整数tag,用最少的bit来描述所有case。
|
|
如果enum总有多个case,但是只有一个关联了data type,其他都没有,我们称这种情况为single-payload enum。此时的原则就是尽量共用空间,无法共用时,增加额外的位来区分情况。
|
|
|
|
如果有大于1个case关联了data type,那么就是Multi-Payload Enums。此时也是一样的尽量共用空间,无法共用时,增加bit进行区分。
|
|
protocol类型、组合协议类型、Any等这些无法确定大小的类型,他们都Existential Container。具有同样的layout。
Existential Containers必须容纳任意大小和对齐的值。此时使用3个指针大小的固定数据区。如果他的大小和对其都小于等于固定缓冲区的大小,则直接包含该值。如果不能包含,这存储一个指向其数据的指针。具体是什么类型,由一个类型元数据记录标识。protocol的方法在witnesstable中。
|
|
|
|
就两个Int的空间。ok,现在我们用Existential Container来存储他:
|
|
前两个为struct的a和b。前3个缓冲区剩余空间会用于存放valuewitnesstable,包含一些初始化函数,如果没空间了就没有这个。第四个为type,第5个为protocol witnesstable。正如我们最开始看到的那样:3个缓冲区,一个type,一个pwt。
AnyObject由于对象都是指针,所以不会存在大小不一致的情况。
|
|
和protocol类似,只是没有了protocol witness table。
|
|
tag:
缺失模块。
1、请确保node版本大于6.2
2、在博客根目录(注意不是yilia根目录)执行以下命令:
npm i hexo-generator-json-content --save
3、在根目录_config.yml里添加配置:
jsonContent: meta: false pages: false posts: title: true date: true path: true text: false raw: false content: false slug: false updated: false comments: false link: false permalink: false excerpt: false categories: false tags: true