裁员寒冬的iOS面试经验(持续更新)

贫道刚入职斗鱼深圳4个月,本以为能安然过个好年,突然来的裁员消息重重给了一锤。进城外来务工人员的悲哀,总结一些面试题供广大道友借鉴,也有些回答不上的欢迎底下探讨。也祝愿大家都能拿到满意的offer。
1、报unrecognized selector sent to instance的Crash之前系统会怎么处理(消息转发机制)?

自己的文章
2、OC的NSError和Swift的Error对象有什么区别?
内部链接
3、哈希表是什么,OC中哪里有用到?
哈希算法详解(腾讯面试官的问题,应用我回答字典,不知道为啥不对)
4、分类的底层实现?
自己的文章
5、数据库使用事务的优缺点?
优点:1、LZ遇到的场景是上百条数据插入数据库时,不使用事务会导致每次操作都要连接数据库,完成操作时间大概在8s。使用事务后操作时间在ms级别。2、当你需要对多个表进行相关性操作时,使用BeginTrans()开启事务,然后操作,如果中间哪个表更新出错了,或者数据有问题,你可以用RollBack()方法在取消之前的相关性操作,如果没有错,那就使用Commit()方法提交你的修改。另外,在这个过程中,所有你改动的内容只对你自己有效,别人不能知道你改了什么,也不能对你正在改的表做修改,直到你提交之后,别人才能修改这些表,检索出你修改过的内容。
缺点:并发问题 解决方案
6、FMDB的原理?
作者有三个篇幅
7、如何保证线程安全?
最简单的方式肯定就是加锁。(面试官还问其他方式,只好找了下资料有系统CAS的方式)
无锁保证线程安全
8、APNS?
裁员寒冬的iOS面试经验(持续更新)
文章图片
流程图
根据图片我们可以概括一下:
1、应用程序注册APNS消息推送。
2、iOS从APNS Server获取devicetoken,应用程序接收device token。
3、应用程序将device token发送给程序的PUSH服务端程序。
4、服务端程序向APNS服务发送消息。
5、APNS服务将消息发送给iPhone应用程序。
9、沙盒目录?
链接
10、Xcode进行编译时会发生什么?
链接
11、单例几种创建方式?
链接
12、UIWebview和WKWebview对比?
文章底部链接不错
13、MD5算法可逆吗?
MD5不可逆的原因是由于它是一种散列函数(也叫哈希函数,哈希函数又称散列函数,杂凑函数,他是一个单向密码体制,即从明文到密文的不可逆映射,只有加密过程没有解密过程,哈希函数可以将任意长度的输入经过变化后得到固定长度的输出,这个固定长度的输出称为原消息的散列或消息映射。 理想的哈希函数可以针对不同的输入得到不同的输出,如果存在两个不同的消息得到了相同的哈希值,那我们称这是一个碰撞),使用的是hash算法,在计算过程中原文的部分信息是丢失了的。一个MD5理论上是可以对应多个原文的,因为MD5是有限多个而原文是无限多个的。MD5码128位2进制数,最多有2^128种可能但是字符串的数量显然是有无数种可能的。
14、ADS和RSA加密?
建议自行搜索资料弄懂对称加密和非对称加密算法,看下原理。
15、Websocket?
链接
16、排序算法以及项目运用?(阿里题)
百度百科重点了解时间复杂度、空间复杂度和原理。
17、autorelease底层原理?
原理
18、SDWebimage缓存图片导致内存一直增加用什么机制处理?
淘汰策略:根据图片使用的次数进行加权,权重高的放在队列前面,将权重低的图片优先剔除出内存。(此策略思路可用在礼物队列方案)
19、打包生成的ipa包里的符号表?
符号表dSYM
20、反编译工具? 裁员寒冬的iOS面试经验(持续更新)
文章图片
常用工具 21、Mach-O文件?
Mach-O结构
22、为什么域名访问比IP慢?
互联网的基础协议是 IP 协议,在IP之上是 TCP/UDP,再往上是 HTTP等应用协议。访问DNS一般来说是很快的,就是一个UDP包来回,但是总要花点时间,所以用域名注定比用IP慢一点。
但是DNS不总是很快的,有时会非常慢,甚至根本就无法使用,这就造成了用域名访问网络会遇到各种不稳定问题。
每台互联网终端设备,比如 PC 手机,都会有一个默认DNS,你在PC上输入 ipconfig /all 就可以看到默认DNS的IP地址。
所谓域名解析服务就是通过查表把域名换算成IP的过程,访问网络的时候把域名发送到DNS服务器,然后从DNS获取解析后的IP地址,如果DNS服务器上有域名到IP的对照表,那么这个解析就很快,如果没有,DNS服务需要向它的上层服务去询问,这样一层一层问上去,直到找到这个对照表为止,这个过程时间就很不可控了,有时几百毫秒,慢起来10秒钟都可能。
如果访问服务器先采用域名访问很慢,然后通过本地nslookup 获得DNS本地缓存映射(域名-IP),直接用IP地址访问很快,即两次访问使用相同的IP地址,两次访问的客户端为同一台机器,那么两次访问的唯一不同:第一次DNS,DNS域名解析会介入一次到多次DNS迭代、递归查询,一句话:会有多次RTT延时的引入。第二次IP,直接就IP封包出去了,所以会快的多。但还有一种场景,有多个服务器(域名一样,但IP不一样)提供服务,有的使用电信的IP,而有的使用联通的IP,如果客户端是电信的,那么域名解析最好是电信的服务器,那么客户端和服务器在电信网络里,访问会快,同理联通的客户端则访问位于联通网络的服务器,智能DNS会根据客户端IP来做出以上的决策。但如果客户端位于电信网络,而返回的服务器IP却位于联通,则流量必须经过电信与联通的互联通道,这个通道比较窄,容易堵车、丢包,给用户的感受就是访问特别慢(丢包特别影响性能)。
采用IP访问快,是因为客户端与服务器IP在一个网络,而DNS域名解析的服务器IP与客户端不在一个网络,丢包、延迟大都会造成所说的访问慢。
23、网络延迟优化?(面试基本都问网络的问题)
移动端网络优化方案
24、大厂的技术对比?(阿里题)
没进过大厂答不上来,望有大佬评论解答下。
25、假设:鸟巢开演唱会,附近基站都无法使用,在只有局域网的情况下,手机端如何进行签到数据上报和同步,具体用到网络协议?
楼主惭愧,最后只好说区块链去中心化思想。
26、OC语言中运用到的设计模式?
1、Category:装饰模式。
2、UIButton的customWithType:工厂模式。
3、UITableview的数据源和代理:代理模式。
4、NSNotification:单例模式(懒汉式和饿汉式创建方式)。
5、KVO:观察者模式。
6、响应者链:责任链模式。
27、项目中的亮点?(阿里必考题)
还是靠大家自己总结,会问细节和技术延伸,楼主的:
1、礼物高并发和图片内存清除处理:前面提到过的权重淘汰机制。
2、Socket数据三层架构:socket连接回调层、数据缓存池调度层、业务接口层。
3、结合mvvm和工厂模式衍变的mvvm变种架构。
4、NSDecimalNumber类型保存高精度数据,可精确到小数点后多位。
5、自封装一套html格式字符串与富文本互转工具类(业务场景不得已的设计,局限性较大,还是服务端处理转换方便可靠)。
6、直播间连麦计费与服务端连接策略。
7、IJKPlayer框架源码bug修改。
8、直播间IM大并发消息处理,加锁和异步执行。
28、浮点数的二进制表示?(阿里题)
浮点数的二进制表示
29、一张图片渲染到页面的过程?
1.假设我们使用 +imageWithContentsOfFile: 方法从磁盘中加载一张图片,这个时候的图片并没有解压缩;
2.然后将生成的 UIImage 赋值给 UIImageView ;
3.接着一个隐式的 CATransaction 捕获到了 UIImageView 图层树的变化;
4.在主线程的下一个 runloop到来时,Core Animation 提交了这个隐式的 transaction ,这个过程可能会对图片进行 copy 操作,而受图片是否字节对齐等因素的影响,这个 copy 操作可能会涉及以下部分或全部步骤:
a、分配内存缓冲区用于管理文件 IO 和解压缩操作;
b、将文件数据从磁盘读到内存中;
c、将压缩的图片数据解码成未压缩的位图形式,这是一个非常耗时的 CPU 操作;
d、最后 Core Animation 使用未压缩的位图数据渲染 UIImageView 的图层。
30、iOS APP 启动性能优化?
启动性能优化
31、iOS证书原理?
链接
32、进程、线程与堆栈的关系?
链接
33、TCP的拥塞控制和流量控制?
链接
34、LLVM比GCC编译器优点?
1、编译速度快:在某些平台上,Clang的编译速度显著的快过GCC(Debug模式下编译OC速度比GGC快3倍)。
2、占用内存小:Clang生成的AST所占用的内存是GCC的五分之一左右 3、模块化设计:Clang采用基于库的模块化设计,易于 IDE 集成及其他用途的重用
4、诊断信息可读性强:在编译过程中,Clang 创建并保留了大量详细的元数据 (metadata),有利于调试和错误报告
5、设计清晰简单,容易理解,易于扩展增强
35、实现字符串拷贝,将src的内容拷贝到desc中?
void str_copy(char* desc, char* src) { for(; *desc++=*src++; ); }

36、递归求解数组中的最大值?
int Max(int A[],int i) { int a; if(i==0)//递归出口 return A[0]; else { a=Max(A,i-1); return ((a>A[i])?a:A[i]); //判断A[i]与a的大小 }

37、对view进行scale动画,改变的是frame还是bounds?
【裁员寒冬的iOS面试经验(持续更新)】frame改变了。如果改变了bounds,则view的子控件也会被更改。
38、互斥锁与信号量的区别?
信号量用在多线程多任务同步的,一个线程完成了某一个动作就通过信号量告诉别的线程,别的线程再进行某些动作(大家都在semtake的时候,就阻塞在那里)。而互斥锁是用在多线程多任务互斥的,一个线程占用了某一个资源,那么别的线程就无法访问,直到这个线程unlock,其他的线程才开始可以利用这 个资源。比如对全局变量的访问,有时要加锁,操作完了,再解锁。有的时候锁和信号量会同时使用的。
也就是说,信号量不一定是锁定某一个资源,而是流程的概念,比如:有A、B两个线程,B线程要等A线程完成某一任务以后再进行自己下面的步骤,这个任务并不一定是锁定某一资源,还可以是进行一些计算或者数据处理之类。而线程互斥量则是锁住某一资源的概念,在锁定期间内,其他线程无法对被保护的数据进 行操作。在有些情况下两者可以互换。
作用域:
信号量: 进程间或线程间(linux仅线程间的无名信号量pthread semaphore)
互斥锁: 线程间
上锁时:
信号量: 只要信号量的value大于0,其他线程就可以sem_wait成功,成功后信号量的value减一。若value值不大于0,则sem_wait使得线程阻塞,直到sem_post释放后value值加一,但是sem_wait返回之前还是会将此value值减一
互斥锁: 只要被锁住,其他任何线程都不可以访问被保护的资源
39、链表中的环,并找到环路起点?
快慢指针找到环,并记录环中节点个数n。再用双指针的第一个指针先走n步,接下来两个指针同时出发,相遇的即为环的起点。
40、海量数据排序——如果有1TB的数据需要排序,但只有32GB的内存如何排序处理?
1、外排序
传统的排序算法一般指内排序算法,针对的是数据可以一次全部载入内存中的情况。但是面对海量数据,即数据不可能一次全部载入内存,需要用到外排序的方法。外排序采用分块的方法(分而治之),首先将数据分块,对块内数据按选择一种高效的内排序策略进行排序。然后采用归并排序的思想对于所有的块进行排序,得到所有数据的一个有序序列。
例如,考虑一个1G文件,可用内存100M的排序方法。首先将文件分成10个100M,并依次载入内存中进行排序,最后结果存入硬盘。得到的是10个分别排序的文件。接着从每个文件载入9M的数据到输入缓存区,输出缓存区大小为10M。对输入缓存区的数据进行归并排序,输出缓存区写满之后写在硬盘上,缓存区清空继续写接下来的数据。对于输入缓存区,当一个块的9M数据全部使用完,载入该块接下来的9M数据,一直到所有的9个块的所有数据都已经被载入到内存中被处理过。最后我们得到的是一个1G的排序好的存在硬盘上的文件。
2、1TB数据使用32GB内存如何排序
①、把磁盘上的1TB数据分割为40块(chunks),每份25GB。(注意,要留一些系统空间!)
②、顺序将每份25GB数据读入内存,使用quick sort算法排序。
③、把排序好的数据(也是25GB)存放回磁盘。
④、循环40次,现在,所有的40个块都已经各自排序了。(剩下的工作就是如何把它们合并排序!)
⑤、从40个块中分别读取25G/40=0.625G入内存(40 input buffers)。
⑥、执行40路合并,并将合并结果临时存储于2GB 基于内存的输出缓冲区中。当缓冲区写满2GB时,写入硬盘上最终文件,并清空输出缓冲区;当40个输入缓冲区中任何一个处理完毕时,写入该缓冲区所对应的块中的下一个0.625GB,直到全部处理完成。
3、继续优化
磁盘I/O通常是越少越好(最好完全没有),那么如何降低磁盘I/O操作呢?关键就在第5和第6步中的40路输入缓冲区,我们可以先做8路merge sort,把每8个块合并为1路,然后再做5-to-1的合并操作。
再深入思考一下,如果有多余的硬件,如何继续优化呢?有三个方向可以考虑:
使用并发:如多磁盘(并发I/O提高)、多线程、使用异步I/O、使用多台主机集群计算。
提升硬件性能:如更大内存、更高RPM的磁盘、升级为SSD、Flash、使用更多核的CPU。
提高软件性能:比如采用radix sort、压缩文件(提高I/O效率)等。
41、atomic关键字原理?
在ios10之前是osspint_lock自旋锁,之后由于优先级反转等性能问题底层又换成os_unfair_lock互斥锁
参考资料
42、NSNotificationCenter原理?
NSNotificationCenter原理
43、dispatch_once原理?
dispatch_once用原子性操作block执行完成标记位,同时用信号量确保只有一个线程执行block,等block执行完再唤醒所有等待中的线程。
dispatch_once原理

    推荐阅读