贫道刚入职斗鱼深圳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?
根据图片我们可以概括一下:
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包里的符号表?
20、反编译工具?
21、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?
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原理?
43、dispatch_once原理?
dispatch_once用原子性操作block执行完成标记位,同时用信号量确保只有一个线程执行block,等block执行完再唤醒所有等待中的线程。
dispatch_once原理
44、Http1.0 2.0 3.0区别?
45、页面push后pop,里面有网络请求block用strong修饰self,页面会马上释放吗?block里面会继续执行吗?
46、frame和bounds除了坐标系以外还有什么区别?
47、Https实际场景的通信?
- 客户端发起HTTPS请求
这个没什么好说的,就是用户在浏览器里输入一个https网址,然后连接到server的443端口。- 服务端的配置
采用HTTPS协议的服务器必须要有一套数字证书,可以自己制作,也可以向组织申请。区别就是自己颁发的证书需要客户端验证通过,才可以继续访问,而使用受信任的公司申请的证书则不会弹出提示页面(startssl就是个不错的选择,有1年的免费服务)。这套证书其实就是一对公钥和私钥。如果对公钥和私钥不太理解,可以想象成一把钥匙和一个锁头,只是全世界只有你一个人有这把钥匙,你可以把锁头给别人,别人可以用这个锁把重要的东西锁起来,然后发给你,因为只有你一个人有这把钥匙,所以只有你才能看到被这把锁锁起来的东西。- 传送证书
这个证书其实就是公钥,只是包含了很多信息,如证书的颁发机构,过期时间等等。- 客户端解析证书
这部分工作是有客户端的TLS来完成的,首先会验证公钥是否有效,比如颁发机构,过期时间等等,如果发现异常,则会弹出一个警告框,提示证书存在问题。如果证书没有问题,那么就生成一个随即值。然后用证书对该随机值进行加密。就好像上面说的,把随机值用锁头锁起来,这样除非有钥匙,不然看不到被锁住的内容。- 传送加密信息
这部分传送的是用证书加密后的随机值,目的就是让服务端得到这个随机值,以后客户端和服务端的通信就可以通过这个随机值来进行加密解密了。- 服务段解密信息
服务端用私钥解密后,得到了客户端传过来的随机值(私钥),然后把内容通过该值进行对称加密。所谓对称加密就是,将信息和私钥通过某种算法混合在一起,这样除非知道私钥,不然无法获取内容,而正好客户端和服务端都知道这个私钥,所以只要加密算法够彪悍,私钥够复杂,数据就够安全。- 传输加密后的信息
这部分信息是服务段用私钥加密后的信息,可以在客户端被还原。- 客户端解密信息
客户端用之前生成的私钥解密服务段传过来的信息,于是获取了解密后的内容。整个过程第三方即使监听到了数据,也束手无策。
48、Autolayou布局在什么时候会转换成frame?
AutoLayout不只是布局算法Cassowary,还包含了布局在运行时的生命周期等一整套布局引擎系统,用来统一管理布局的创建、更新和销毁。这一整套布局引擎系统叫做Layout Engine,是AutoLayout的核心,主导整个界面布局。
在每个视图得到自己的布局之前,Layout Egine会将视图、约束、优先级、固定大小通过计算转换成最终的大小和位置。在Layout Engine里,每当约束发生变化,就会触发Deffered Layout Pass。完成后进入监听约束变化的状态。当再次监听到约束变化,即进入下一轮循环。
图中,Constraints Change表示的就是约束变化,添加、删除视图时会触发约束变化。Activating或Deactivating,设置Constant或Priority时也会触发约束变化。Layout Engine在碰到约束变化后会重新计算布局,获取到布局后调用superView.setNeedsLayout(),然后进到Deferred Layout Pass。
Deferred Layout Pass的主要作用是做容错处理。如果有些视图在更新约束时没有确定或者缺失布局声明的话,会先在这里做容错处理。
接下来,Layout Engine会从上到下调用layoutSubviews(),通过Cassowary算法计算各个子视图的位置,算出来后将子视图的frame从Layout Engine拷贝出来。
在这里之后的处理,就和手写布局绘制、渲染过程一样了。所以,使用Auto Layout和手写布局的区别,就是多了一个布局上的计算过程。
49、分辨率10241024的png图片2M和jpg图片500k上屏时内存占用多少?*
50、SDWebImage框架的优缺点?
51、assign修饰对象会怎么样?
首先我们需要明确,对象的内存一般被分配到堆上,基本数据类型和oc数据类型一本被分配在栈上。
如果用assign修饰对象,当对象释放后(因为不存在强引用,离开作用域对象内存可能被回收),指针的地址还是存在的,也就是说指针并没有被置为nil,下次再访问该对象就会造成野指针异常。对象是分配在堆上的,堆上的内存由程序员手动释放。
assign修饰基本数据类型或OC数据类型,因为基本数据类型是分配在栈上的,由系统分配和释放,所以不会造成野指针。
52、内存分为几个部分,实例对象在哪里,类对象在哪里,元类对象在哪里?
堆、栈、全局区、代码区、常量区。
instance----0x7f9ef0e0c540 0x7f9ef0e0d000
class---0x1021c5930 0x1021c5930 0x1021c5930 0x1021c5930 0x102a002e0
meta---0x102a002b8 0x1021c5958 0x1021c5958 0x102a002b8