2020年春季iOS面试总结

1、内存管理

iOS中的内管理主要是通过引用计数来管理内存的。分为自动管理(ARC)和手动管理(MRC),以及autorelease。管理的的对象主要是值类型(int、float、struct等基本数据类型)和引用类型(即继承自NSObject类的所有的OC对象)。

那么MRC、ARC和autorelease的区别有哪些呢?MRC为手动引用计数,ARC为自动引用计数,autorelease则是添加到自动释放池中。

1.1、ARC和MRC的区别:ARC相对于MRC,不需要手动书写retain/release/autorelease,而是在编译期和运行期这两部分帮助开发者管理内存。

在编译器的时候,ARC调用C接口实现的retain/release/autorelease,在运行期的时候使用runtime配合来实现内存管理。

1.2、autorelease分为两种情况:手动干预释放时机、系统自动释放。

手动干预释放机制:指定autoreleasepool,就是所谓的作用域大括号结束释放;

系统自动释放:不手动指定autoreleasepool。

autorelease对象除了作用域后,会被添加到最近一次创建的自动释放池中,并会在当前的runloop迭代结束时释放。

ps:runloop从程序启动到加载完成是一个完整的运行循环,然后会停下来,等待用户交互,用户的每一次交互都会启动一次运行循环,这时候会创建自动释放池,来处理用户所有的点击事件、触摸事件,在一次完整的运行循环结束之前,会销毁自动释放池,达到销毁对象的目的。

1.3、retain、release、autorelease

1.3.1、retain是调用了sidetable_retain方法,retain通过Sidetable这个数据结构来存储引用计数,Sidetable存储了一个自旋锁,一个引用计数,这个引用计数的以对象的地址作为key,引用计数作为value,到这里,引用计数的底层已经清楚了。

1.3.2、release的通过查找对象,对引用计数减1,如果引用计数小于阈值,则调用SEL_dealloc

1.3.3、autorelease方法的作用是把对象放到autorelease pool中,到pool drain的时候,回释放池中的对象。放到自动释放池中的对象在超出作用域后会立即释放。事实上在iOS 程序启动之后,主线程会启动一个Runloop,这个Runloop在每一次循环是被自动释放池包裹的,在合适的时候对池子进行清空。autorelease方法会把对象存储到AutoreleasePoolPage的链表里。等到auto release pool被释放的时候,把链表内存储的对象删除。所以,AutoreleasePoolPage就是自动释放池的内部实现。

1.4、与内存有关的修饰符

strong :强引用,ARC中使用,与MRC中retain类似,使用之后,计数器+1。

weak :弱引用 ,ARC中使用,如果只想的对象被释放了,其指向nil,可以有效的避免野指针,其引用计数为1。

readwrite : 可读可写特性,需要生成getter方法和setter方法时使用。

readonly : 只读特性,只会生成getter方法 不会生成setter方法,不希望属性在类外改变。

assign :赋值特性,不涉及引用计数,弱引用,setter方法将传入参数赋值给实例变量,仅设置变量时使用。

retain :表示持有特性,setter方法将传入参数先保留,再赋值,传入参数的retaincount会+1。

copy :表示拷贝特性,setter方法将传入对象复制一份,需要完全一份新的变量时。

nonatomic :非原子操作,不加同步,多线程访问可提高性能,但是线程不安全的。决定编译器生成的setter getter是否是原子操作。

atomic :原子操作,同步的,表示多线程安全,与nonatomic相反。

1.5、在ARC的项目中,对MRC的文件可以添加编译选项-fno-objc-arc的标识;在MRC的项目中,对ARC的文件可以添加编译选项 -fobjc-arc的标识。把MRC文件转为ARC,实际上是去掉文件中的retain、release。

参考链接:https://www.jianshu.com/p/139ec8f2d95d

2、KVC

KVC也就是key-value-coding,即键值编码,通常是用来给某一个对象的属性进行赋值。既然可以通过kvc赋值,同样的也可以通过它进行取值。

2.1、最常见的两种用法就是:a、对私有变量进行赋值;b、字典转模型。

2.2、需要注意:a、字典转模型的时候,字典中的某一个key一定要在模型中有对应的属性;b、如果一个模型中包含了另外的模型对象,是不能直接转化成功的;c、通过kvc转化模型中的模型,也是不能直接转化成功的。

3、KVO

KVO,即key-value-observing,利用一个key来找到某个属性并监听其值得改变。其实这也是一种典型的观察者模式。

3.1、简单的说,kvo的用法非常简单:a、添加观察者;b、在观察者中实现监听方法,observeValueForKeyPath: ofObject: change: context:(通过查阅文档可以知道,绝大多数对象都有这个方法,因为这个方法属于NSObject);c、移除观察者。

3.2、KVO的底层实现

当一个类的属性被观察的时候,系统会通过runtime动态的创建一个该类的派生类,并且会在这个类中重写基类被观察的属性的setter方法,而且系统将这个类的isa指针指向了派生类,从而实现了给监听的属性赋值时调用的是派生类的setter方法。重写的setter方法会在调用原setter方法前后,通知观察对象值得改变。

* 貌似有个facebook开源的工具,KVOController ,是一个简单安全的 KVO(Key-value Observing,键-值 观察)工具,好像挺好用的。

3.3、总结一下:1.KVO KVC 没联系;2.KVO 是监听属性值的改变;3.KVO 底层实现原理是系统给当前类创建子类 , 在子类 setter 方法调用父类的 setter 方法。

参考链接:https://www.jianshu.com/p/f1393d10109d

4、RunTime

Objective-C是基于C语言加入了面向对象特性消息转发机制的动态语言,这意味着它不仅需要一个编译器,还需要Runtime系统来动态创建类和对象,进行消息发送和转发。

在Objective-C中,使用[receiver message]语法并不会马上执行receiver对象的message方法的代码,而是向receiver发送一条message消息,这条消息可能由receiver来处理,也可能由转发给其他对象来处理,也有可能假装没有接收到这条消息而没有处理。其实[receiver message]被编译器转化为:idobjc_msgSend (idself, SEL op, ... );可以从两个数据结构id和SEL来逐步分析和理解Runtime有哪些重要的数据结构。

主要作用:a、获取一个类的全部成员变量就算是私有成员变量也可以获取的到;b、我们可以获取到一个类的全部属性名;c、获取一个类的全部方法;d、获取一个类中遵守的全部协议;e、归档/解档;f、交换两个方法的实现,拦截系统自带的方法调用功能。

参考链接:https://www.jianshu.com/p/ebc6e20b84cf

5、RunLoop

 RunLoop 就是一个事件处理的循环,用来不停的调度工作以及处理输入事件。使用 RunLoop 的目的是让你的线程在有工作的时候忙于工作,而没工作的时候处于休眠状态。 runloop 的设计是为了减少 cpu 无谓的空转。

5.1、runloop保证线程的长久存活

        使用多线程时,一个子线程当它的任务执行完毕之后都会销毁,所以每次执行异步任务都会频繁去创建和销毁线程,这样无疑是耗费资源的。这种情况下我们可以利用runloop来保证线程在执行完任务后不背销毁而进入“休眠”状态,等待下一个任务的执行再被唤醒。

5.2、保证NSTimer正常运转。 

5.3、滚动视图流畅性优化

        在我们的开发过程中经常遇到列表型上面有图片的,一般下载图片用异步,setimage则使用同步。为imageView设置image,是在UITrackingRunLoopMode中也可以进行的,如果图片很大,图片解压缩和渲染肯定会很耗时,那么卡顿就是必然的。我们可以再setImage的时候手动设置runloop的mode来解决。

5.4、监测iOS卡顿

        在写代码之前我们首先要了解几个原理,dispatch_semaphore_t这个类,dispatch_semaphore_t 是一个信号量机制,信号量到达、或者 超时会继续向下进行,否则等待,如果超时则返回的结果必定不为0,信号量到达结果为0。在就是根据CFRunLoopActivity的几个状态以及Runloop执行的顺序过程、原理我们可以通过监听mainRunloop的状态和信号量阻塞线程的特点来检测卡顿了。

6、NSThread、GCD、NSOperation多线程

6.1、NSThread是封装程度最小最轻量级的,使用更灵活,但要手动管理线程的生命周期、线程同步和线程加锁等,开销较大;

6.2、GCD基于C语言封装的,遵循FIFO;

6.3、NSOperation基于GCD封装的,比GCD可控性更强;可以加入操作依赖(addDependency)、设置操作队列最大可并发执行的操作个数(setMaxConcurrentOperationCount)、取消操作(cancel)等,需要使用两个它的实体子类:NSBlockOperation和NSInvocationOperation,或者继承NSOperation自定义子类;NSBlockOperation和NSInvocationOperation用法的主要区别是:前者执行指定的方法,后者执行代码块,相对来说后者更加灵活易用。NSOperation操作配置完成后便可调用start函数在当前线程执行,如果要异步执行避免阻塞当前线程则可以加入NSOperationQueue中异步执行。

7.iOS设计模式

7.1、适配器模式;

1:何为适配器模式?

适配器模式将一个类的接口适配成用户所期待的。一个适配器通常允许因为接口不兼容而不能一起工作的类能够在一起工作,做法是将类自己的接口包裹在一个已存在的类中。

2:[如何使用适配器模式?]

当你想使用一个已经存在的类,而它的接口不符合你的需求;

你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作;

你想使用一些已经存在的子类,但是不可能对每一个都进行子类化以匹配它们的接口,对象适配器可以适配它的父亲接口。

3:[适配器模式的优缺点?]

优点:降低数据层和视图层(对象)的耦合度,使之使用更加广泛,适应复杂多变的变化。

缺点:降低了可读性,代码量增加,对于不理解这种模式的人来说比较难看懂。

7.2、策略模式;

1:何为策略模式?策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。

2:如何使用策略模式?

在有多种算法相似的情况下,使用 if…else 所带来的复杂和难以维护。

如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。

一个系统需要动态地在几种算法中选择一种。

如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。

注意事项:如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。

3:策略模式的优缺点?

优点:简化操作,提高代码维护性。算法可以自由切换,避免使用多重条件判断,扩展性良好。

缺点:在使用之前就要确定使用某种策略,而不是动态的选择策略。策略类会增多,所有策略类都需要对外暴露。

7.3、观察者模式;

1:[何为观察者模式?]

当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。

2:如何使用观察者模式?

一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。

3:观察者模式的优缺点?

优点:观察者和被观察者是抽象耦合的。建立一套触发机制。缺点:如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

7.4、原型/外观模式;

1:何为原型/外观模式?

原型模式:(Prototype Pattern)用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。

外观模式:(Facade Pattern)隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性。这种模式涉及到一个单一的类,该类提供了客户端请求的简化方法和对现有系统类方法的委托调用。

2:如何使用原型/外观模式?

7.4.3、原型模式:

当一个系统应该独立于它的产品创建,构成和表示时。

当要实例化的类是在运行时刻指定时,例如,通过动态装载。

为了避免创建一个与产品类层次平行的工厂类层次时。

当一个类的实例只能有几个不同状态组合中的一种时。建立相应数目的原型并克隆它们可能比每次用合适的状态手工实例化该类更方便一些。

7.4.4、外观模式:

客户端不需要知道系统内部的复杂联系,整个系统只需提供一个"接待员"即可。

定义系统的入口。

7.5.5、:原型/外观模式的优缺点?

原型模式:

优点:性能提高,逃避构造函数的约束。

缺点:

配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类不是很难,但对于已有的类不一定很容易。

必须实现 Cloneable 接口。

逃避构造函数的约束。

外观模式

优点:减少系统相互依赖、提高灵活性、提高了安全性。

缺点:不符合开闭原则,如果要改东西很麻烦,继承重写都不合适。

7.5、工厂模式;

1:何为工厂模式?

这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

2:如何使用工厂模式?

我们明确地计划不同条件下创建不同实例时。

作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过 new 就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。

3:工厂模式的优缺点?

优点:

一个调用者想创建一个对象,只要知道其名称就可以了。

扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。

屏蔽产品的具体实现,调用者只关心产品的接口。

缺点:

每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。

7.6、桥接模式;

1:何为桥接模式?

桥接(Bridge)是用于把抽象化与实现化解耦,使得二者可以独立变化。这种类型的设计模式属于结构型模式,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。

这种模式涉及到一个作为桥接的接口,使得实体类的功能独立于接口实现类。这两种类型的类可被结构化改变而互不影响。

2:如何使用桥接模式?

在有多种可能会变化的情况下,用继承会造成类爆炸问题,扩展起来不灵活。

实现系统可能有多个角度分类,每一种角度都可能变化。

把这种多角度分类分离出来,让它们独立变化,减少它们之间耦合。

3:桥接模式的优缺点?

优点 :抽象和实现的分离、优秀的扩展能力、实现细节对客户透明。

缺点:桥接模式的引入会增加系统的理解与设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程。

7.7、代理模式;

1:何为代理模式?

在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。

在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。

2:如何使用代理模式?

在直接访问对象时带来的问题,比如说:要访问的对象在远程的机器上。在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层。

想在访问一个类时做一些控制。

3:代理模式的优缺点?

优点:

职责清晰、高扩展性、智能化。

缺点:

由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。

实现代理模式需要额外的工作,有些代理模式的实现非常复杂。

7.8、单例模式;

1:何为单例模式?

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

注意:

单例类只能有一个实例。

单例类必须自己创建自己的唯一实例。

单例类必须给所有其他对象提供这一实例。

2:如何使用单例模式?

当您想控制实例数目,节省系统资源的时候。

3:单例模式的优缺点?

优点:

在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)。

避免对资源的多重占用比如写文件操作。

缺点:

没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。

7.9、备忘录模式;

1:何为备忘录模式?

备忘录模式(Memento Pattern)保存一个对象的某个状态,以便在适当的时候恢复对象。备忘录模式属于行为型模式。

2:如何使用备忘录模式?

很多时候我们总是需要记录一个对象的内部状态,这样做的目的就是为了允许用户取消不确定或者错误的操作,能够恢复到他原先的状态,使得他有"后悔药"可吃。

3:备忘录模式的优缺点?

优点:

给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态。

实现了信息的封装,使得用户不需要关心状态的保存细节。

缺点:

消耗资源。如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存。

7.10、生成器模式;

1:何为送生成器模式?

建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

2:如何使用生成器模式?

主要解决在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。

一些基本部件不会变,而其组合经常变化的时候。

3:生成器模式的优缺点?

优点:

建造者独立,易扩展。

便于控制细节风险。

缺点:

产品必须有共同点,范围有限制。

如内部变化复杂,会有很多的建造类。

7.11、命令模式;

1:何为命令模式?

命令模式(Command Pattern)是一种数据驱动的设计模式,它属于行为型模式。请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。

主要解决的问题?

在软件系统中,行为请求者与行为实现者通常是一种紧耦合的关系,但某些场合,比如需要对行为进行记录、撤销或重做、事务等处理时,这种无法抵御变化的紧耦合的设计就不太合适。

2:如何使用命令模式?

在某些场合,比如要对行为进行"记录、撤销/重做、事务"等处理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将"行为请求者"与"行为实现者"解耦?将一组行为抽象为对象,可以实现二者之间的松耦合。

3:命令模式的优缺点?

优点:降低了系统耦合度,新的命令可以很容易添加到系统中去。

缺点:使用命令模式可能会导致某些系统有过多的具体命令类。

8、简述weak的实现原理

8.1.1、weak 关键字的作用弱引用,所引用对象的计数器不会加一,并在引用对象被释放的时候自动被设置为 nil;

8.1.2、weak是有Runtime维护的weak表;

8.1.3、weak释放为nil过程

weak被释放为nil,需要对对象整个释放过程了解,如下是对象释放的整体流程:

8.2.1、调用objc_release

8.2.2、因为对象的引用计数为0,所以执行dealloc

8.2.3、在dealloc中,调用了_objc_rootDealloc函数

8.2.4、在_objc_rootDealloc中,调用了object_dispose函数

8.2.5、调用objc_destructInstance

8.2.6、最后调用objc_clear_deallocating。

对象准备释放时,调用clearDeallocating函数。clearDeallocating函数首先根据对象地址获取所有weak指针地址的数组,然后遍历这个数组把其中的数据设为nil,最后把这个entry从weak表中删除,最后清理对象的记录。其实Weak表是一个hash(哈希)表,然后里面的key是指向对象的地址,Value是Weak指针的地址的数组。

总结:weak是Runtime维护了一个hash(哈希)表,用于存储指向某个对象的所有weak指针。weak表其实是一个hash(哈希)表,Key是所指对象的地址,Value是weak指针的地址(这个地址的值是所指对象指针的地址)数组。

9、音视频相关

采集视频,音频–》使用iOS原生框架 AVFoundation.framework

视频滤镜处理–》使用iOS原生框架 CoreImage.framework;使用第三方框架 GPUImage.framework

9.1、CoreImage 与 GPUImage 框架比较:

在实际项目开发中,开发者更加倾向使用于GPUImage框架.

首先它在使用性能上与iOS提供的原生框架,并没有差别;其次它的使用便利性高于iOS原生框架,最后也是最重要的GPUImage框架是开源的.而大家如果想要学习GPUImage框架,建议学习OpenGL ES,其实GPUImage的封装和思维都是基于OpenGL ES.

9.2、视频\音频编码压缩

视频: 使用FFmpeg,X264算法把视频原数据YUV/RGB编码成H264

音频: 使用fdk_aac 将音频数据PCM转换成AAC

视频: VideoToolBox框架

音频: AudioToolBox 框架

硬编码

软编码

9.3、推流

流媒体协议: RTMP\RTSP\HLS\FLV

视频封装格式: TS\FLV

音频封装格式: Mp3\AAC

推流: 将采集的音频.视频数据通过流媒体协议发送到流媒体服务器

推流技术

流媒体服务器

数据分发

截屏

实时转码

内容检测

9.4、拉流

拉流: 从流媒体服务器中获取音频\视频数据

流媒体协议: RTMP\RTSP\HLS\FLV

9.5、音视频解码

视频: 使用FFmpeg,X264算法解码

音频: 使用fdk_aac 解码

视频: VideoToolBox框架

音频: AudioToolBox 框架

硬解码

软解码

9.6、播放

ijkplayer,kxmovie 都是基于FFmpeg框架封装的

ijkplayer 播放框架

kxmovie 播放框架

10、对称加密和非对称加密

10.1、对称密钥加密是指加密和解密使用同一个密钥的方式,这种方式存在的最大问题就是密钥发送问题,即如何安全地将密钥发给对方;

为什么叫对称加密?一方通过密钥将信息加密后,把密文传给另一方,另一方通过这个相同的密钥将密文解密,转换成可以理解的明文。他们之间的关系如下:明文<->密钥<->密文

10.2、非对称加密是指使用一对非对称密钥,即公钥和私钥,公钥可以随意发布,但私钥只有自己知道。发送密文的一方使用对方的公钥进行加密处理,对方接收到加密信息后,使用自己的私钥进行解密。

非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。

10.3、由于非对称加密的方式不需要发送用来解密的私钥,所以可以保证安全性;但是和对称加密比起来,它非常的慢,所以我们还是要用对称加密来传送消息,但对称加密所使用的密钥我们可以通过非对称加密的方式发送出去。但是此时交换的两个公钥不一定正确。

11、证书机制

11.1、作为服务端的小红,首先把自己的公钥发给证书颁发机构,向证书颁发机构申请证书。

11.2、证书颁发机构自己也有一对公钥私钥。机构利用自己的私钥来加密Key1,并且通过服务端网址等信息生成一个证书签名,证书签名同样经过机构的私钥加密。证书制作完成后,机构把证书发送给了服务端小红。

11.3、当小灰向小红请求通信的时候,小红不再直接返回自己的公钥,而是把自己申请的证书返回给小灰。

11.4、小灰收到证书以后,要做的第一件事情是验证证书的真伪。需要说明的是,各大浏览器和操作系统已经维护了所有权威证书机构的名称和公钥。所以小灰只需要知道是哪个机构颁布的证书,就可以从本地找到对应的机构公钥,解密出证书签名。

12、Http和Https的区别

Http协议运行在TCP之上,明文传输,客户端与服务器端都无法验证对方的身份;Https是身披SSL(Secure Socket Layer)外壳的Http,运行于SSL上,SSL运行于TCP之上,是添加了加密和认证机制的HTTP。二者之间存在如下不同:

a、端口不同:Http与Http使用不同的连接方式,用的端口也不一样,前者是80,后者是443;

b、资源消耗:和HTTP通信相比,Https通信会由于加减密处理消耗更多的CPU和内存资源;

c、开销:Https通信需要证书,而证书一般需要向认证机构购买;

d、Https的加密机制是一种共享密钥加密和公开密钥加密并用的混合加密机制。

13、iOS中的图形绘制

13.1、iOS支持OpenGL ES和Quartz/UIKit/CoreAnimation绘制接口。UIKit绘制必须在主线程中完成。

13.2、Quartz支持基于路径的绘制,反走样,填充,图像,上色,坐标变换,pdf绘制显示解析等功能。

13.3、UIKit支持线条绘制、图像和颜色操作。

13.4、Core Animation支持动画绘制。

13.5、View的使用DrawRect绘制,以下行为会触发:

a、 View的移动和遮挡。

b、 View的隐藏和显示。

c、 拖动View。

e、 显示调用setNeedDisplay和setNeedDispalyRect

13.6、UIKit左上角为原点,右下角为终点。CoreAnimation坐下角为原点,右上角为终点。使用CGContextRotateCTM、 CGContextScaleCTM、CGContextTranslateCTM来变换矩阵,或者直接使用CGAffineTransform设置变换 矩阵。

13.7、CGContext绘制上下文,对于Bitmap和PDF,可以创建不同的context类型。

a、 变换矩阵

b、 裁剪范围

c、 线条绘制属性

d、 曲线精度

e、 反走样

f、 填充属性,描边属性

g、 半透明属性

h、 颜色空间

i、 文字

j、 颜色混合模式

13.8、使用UIGraphicsGetCurrentContext来获取当前的CGContext。

13.9、UIGraphicsBeginImageContextWithOptions和UIGraphicsEndImageContext用来包含图像绘制的代码。

     UIGraphicsBeginPDFContextToFile(ToData)和UIGraphicsEndPDFContext用来包含PDF绘制的代码。

13.10、Path绘制,即向量绘制。推荐使用UIBezierPath,其次是CGPath。

13.11、翻转屏幕变换:

CGContextTranslateCTM(graphicsContext, 0.0, drawingRect.size.height);

CGContextScaleCTM(graphicsContext, 1.0, -1.0);

13.12、Point通常等于Pixel,但是可以指定一个Point对应多个Pixel。

13.13、使用UIColor坐颜色空间变换。

13.14、绘制性能:

a、 最小化绘制调用

b、 尽量使用不透明的View

c、 在卷屏时重用View和表格

d、 在卷屏时可以不清空上次绘制结果

e、 减少绘制状态切换。

参考链接:https://www.cnblogs.com/linxiu-0925/p/5070693.html

14、iOS中的动画

Core Animation 流水线的详细过程如下:

首先,由 app 处理事件(Handle Events),如:用户的点击操作,在此过程中 app 可能需要更新视图树,相应地,图层树也会被更新。

其次,app 通过 CPU 完成对显示内容的计算,如:视图的创建、布局计算、图片解码、文本绘制等。在完成对显示内容的计算之后,app 对图层进行打包,并在下一次 RunLoop 时将其发送至 Render Server,即完成了一次 Commit Transaction 操作。

Render Server 主要执行 Open GL、Core Graphics 相关程序,并调用 GPU

GPU 则在物理层上完成了对图像的渲染。

最终,GPU 通过 Frame Buffer、视频控制器等相关部件,将图像显示在屏幕上。

参考链接:https://www.cnblogs.com/feng9exe/p/10912767.html

15、iOS中的直播开发

iOS客户端要实现直播功能,需要经过流程为:

      采集-处理-编码-封包-推流-播放

15.1、采集:

视频通过摄像头进行采集,需要用到iOS底层库AVCaptureSession,音频通过麦克风进行采集,需要用到底层库AudioMedia

15.2、处理:

对视频加美颜、水印,主要使用openGL来实现,GPUImage是一个基于openGL一个强大的图像/视频处理框架,封装好了各种滤镜同时也可以编写自定义的滤镜,其本身内置了多达120多种常见的滤镜效果。

15.3、编码:

不管是视频,还是音频,最好使用硬编,可以减少手机的发热量,效率也比较高。视频编码可以使用VideoToolbox,苹果自带的视频硬解码和硬编码API,但是在iOS8之后才开放。音频采用AudioToolbox ,苹果自带的音频硬解码和硬编码API。

15.4、封包和推流:

使用CDN即分发网络,将视频和音频推送到观众端,可以看到直播内容。虽然分发网络和iOS客户端没有关系,但是作为直播app,还是有优化空间的,比如动态码率优化,码率很高的话,需要的流量会很多,要求网速快,当网速很慢的情况下,需要对画面的质量或者说分辨率进行取舍,让码率降下来,以适应网络环境差的情况。

15.5、播放:

播放器可以做一些优化,当网络卡的情况下,主播这边还是在不断地推流,播放器将推流的信息缓存下来,进行播放,卡得越频繁,造成得延迟就越大,所以要做累计延迟优化,也就是在缓存很多信息时,可以选择性地将中间一些东西丢掉,因为对于直播而言,实时性是很重要得。

参考链接:https://www.jianshu.com/p/b102cf96de94

你可能感兴趣的:(2020年春季iOS面试总结)