iOS面试
- 智力题
- 计算机基础
- 面向对象的三个要素?
- 堆和栈的区别?
- HTTP和HTTPS区别?
- OSI七层模型和五层模型以及对应的协议?
- HTTP头域包括?说几个状态码?
- https一定是安全的吗?
- TCP和UDP的区别?
- TCP三次握手过程理解?
- TCP四次挥手过程理解 ?
- 为什么连接的时候是三次握手,关闭的时候却是四次握手?
- 输入URL后发生了什么?
- iOS开发相关
- 基本数据类型内存占用大小?
- Java,python,OC运行效率孰高?
- OC存在多重继承吗?
- 页面间的传值方式有哪些?
- iOS 关于通知发送与接收的线程问题?
- 沙盒的目录结构?
- Property(nonatomatic, copy) NSMutableArray有什么问题?
- 代理的属性修饰关键字?
- UIViewController的生命周期
- APP的生命周期
- iOS面试题:Autorelease的原理 ?
- Delegate和Notification的区别?
- 对象的copy与mutableCopy?
- GPUImage基本概念
- Cocoapods冲突解决?
- 表视图的滑动卡顿的优化方法?
- iOS单元测试框架
- 对于代码NSString*nc= [[NSArray alloc] init]; 编译时类型和运行时类型?
- iOS中多线程一般有几个方案?
- git rebase和git merge的区别
- pod install 和pod update区别
- 多个网络请求ABC执行完再执行D,如何设计方案?
- iOS为什么使用久了不卡?
- 反问?
- iOS以后的发展方向?
智力题
64匹马8个跑道,至少需要多少轮才能挑选出最快的4匹马
11次
理由: 64批 8个一次 一共八次
后四组淘汰,前四组晋级。 前四组的后四个淘汰前四个晋级。
这时候还有4*4 一共16批马
第四名所在组的后三名淘汰、第三名所在组的后两名淘汰、第二名所在组的最后一名淘汰
这时候还有4+3+2+1 = 10 此时第一组的第一名一定晋级 所以还有9匹
剩下九匹跑两次
所以8+1+2 = 11次
两个人玩抛硬币的游戏,谁先抛到正面就获胜。那么先抛的人获胜概率为()。
2/3第1把胜 1/2 (A正)
第2把胜 1/2 * 1/2 * 1/2 (A反B反A正)
第n把胜 1/2^(2n-1)
A胜的概论,就是上述概率之和。
按等比数列求和公式,当 n 无穷大时,其值是 2/3。
计算机基础
面向对象的三个要素?
封装继承多态
面向对象五个基本原则?
单一指责原则、开闭原则、依赖倒置原则、迪米特法则、里氏替换法则
堆和栈的区别?
1.栈区(stack):由编译器自动分配释放,存放函数的参数值,局部变量等值。其操作方式类似于数据结构中的栈。2.堆区(heap):一般由程序员分配释放,若程序员不释放,则可能会引起内存泄漏。其类似于链表。
HTTP和HTTPS区别?
http 和 https 使用的是完全不同的连接方式,用的端口也不一样,前者是 80,后者是 443。https 是http+ssl(安全套接层)
OSI七层模型和五层模型以及对应的协议?
OSI七层网络模型 | TCP/IP五层网络模型 | 对应网络协议 |
---|---|---|
应用层 | 应用层 | HTTP、TFTP、FTP、NFS、WAIS、SMTP |
表示层 | 应用层 | Telnet、Rlogin、SNMP、Gopher |
会话层 | 应用层 | SMTP、DNSr |
传输层 | 传输层 | TCP、UDP |
网络层 | 网络层 | IP、ICMP、UUCP、ARP、RARP、AKP |
数据链路层 | 数据链路层 | FDDI、Ethernet、Arpanet、PDN、SLIP、PPP |
物理层 | 物理层 | IEEE 802.1A、IEEE802.2到IEEE 802.11 |
HTTP头域包括?说几个状态码?
通用头、请求头、响应头和实体头四部分。
100:客户端应当继续发送请求的剩余部分
200:请求已成功
304:自从上次请求后,请求的网页未修改过。服务器返回此响应时,不会返回网页内容。(缓存)
400:语义有误
404:请求失败,请求所希望得到的资源未在服务器上被发现
500:服务器遇到了一个未曾预料的状况,无法完成请求
509:服务器达到带宽限制
https一定是安全的吗?
https不一定全是安全的,一些网站会使用自签名证书。
自签名证书是指不受信任的任意机构或个人,使用工具自己签发的SSL证书。不是从公共证书机构(CA)那里申请来的证书,没有第三方监督审核,不受浏览器和操作系统信任,常被用于伪造证书进行中间人攻击,劫持SSL加密流量。
TCP和UDP的区别?
TCP是面向连接、可靠、传输速率慢、传输大量数据
UDP是面向无连接、不可靠、少量数据、快
TCP三次握手过程理解?
第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SENT状态,等待服务器确认;
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包。
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),
TCP四次挥手过程理解 ?
四次握手是指终止TCP连接协议时,需要在客户端和服务器之间发送四个包第一次挥手:主动关闭方发送第一个包,其中FIN标志位为1,发送顺序号seq为X。
第二次挥手:被动关闭方收到FIN包后发送第二个包,其中发送顺序号seq为Z,接收顺序号ack为X+1。
第三次挥手:被动关闭方再发送第三个包,其中FIN标志位为1,发送顺序号seq为Y,接收顺序号ack为X。
第四次挥手:主动关闭方发送第四个包,其中发送顺序号为X,接收顺序号为Y。至此,完成四次挥手。
为什么连接的时候是三次握手,关闭的时候却是四次握手?
答:因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。
输入URL后发生了什么?
1、DNS域名解析
2、建立TCP
3、发送HTTP请求
4、服务器处理请求
5、返回响应结果
6、关闭TCP链接
7、浏览器解析HTML
8、浏览器布局渲染
什么是死锁?
死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程
iOS开发相关
基本数据类型内存占用大小?
Java,python,OC运行效率孰高?
OC,直接生成机器码。java是静态语言静态编译,直接执行。而python是动态类型语言,一边编译一边执行。
OC存在多重继承吗?
必然不存在
页面间的传值方式有哪些?
(公有属性,公有方法和协议,block传值,通知,extern全局变量传值,NSUserDefault简单数据存储传值)
iOS 关于通知发送与接收的线程问题?
Notification 是在同一个线程完成post和observer的处理。iOS接受通知的方法所在线程跟注册通知的时候所在线程无关,跟发送通知时候所在线程相关(与发送通知所在线程一致), 如果子线程发的通知 接收通知的时候要刷新UI操作 记得回到主线程
iOS数据本地持久化方法?
plist文件(序列化)、preference(偏好设置)、NSKeyedArchiver(归档)、SQLite3、FMDB、CoreData、沙盒
沙盒的目录结构?
1、Documents 目录:您应该将所有的应用程序数据文件写入到这个目录下。这个目录用于存储用户数据。该路径可通过配置实现iTunes共享文件。可被iTunes备份。2、AppName.app 目录:这是应用程序的程序包目录,包含应用程序的本身。由于应用程序必须经过签名,所以您在运行时不能对这个目录中的内容进行修改,否则可能会使应用程序无法启动。3、Library 目录:这个目录下有两个子目录:
Preferences 目录:包含应用程序的偏好设置文件。您不应该直接创建偏好设置文件,而是应该使用NSUserDefaults类来取得和设置应用程序的偏好.
Caches 目录:用于存放应用程序专用的支持文件,保存应用程序再次启动过程中需要的信息。
可创建子文件夹。可以用来放置您希望被备份但不希望被用户看到的数据。该路径下的文件夹,除Caches以外,都会被iTunes备份。4、tmp 目录:这个目录用于存放临时文件,保存应用程序再次启动过程中不需要的信息。该路径下的文件不会被iTunes备份。
Property(nonatomatic, copy) NSMutableArray有什么问题?
addObject、removeobject可能会崩溃
代理的属性修饰关键字?
@property(nonatomic,assign)
UIViewController的生命周期
按照执行顺序排列:
initWithCoder:通过nib文件初始化时触发。
awakeFromNib:nib文件被加载的时候,会发生一个awakeFromNib的消息到nib文件中的每个对象。
loadView:开始加载视图控制器自带的view。
viewDidLoad:视图控制器的view被加载完成。
viewWillAppear:视图控制器的view将要显示在window上。
updateViewConstraints:视图控制器的view开始更新AutoLayout约束。
viewWillLayoutSubviews:视图控制器的view将要更新内容视图的位置。
viewDidLayoutSubviews:视图控制器的view已经更新视图的位置。
viewDidAppear:视图控制器的view已经展示到window上。
viewWillDisappear:视图控制器的view将要从window上消失。
viewDidDisappear:视图控制器的view已经从window上消失。
APP的生命周期
1、Not running未运行:app没启动或被迫终止。2、Inactive未激活:当前应用正在前台运行,但是并不接收事件(当前或许正在执行其它代码)。一般每当应用要从一个状态切换到另一个不同的状态时,中途过渡会短暂停留在此状态。唯一在此状态停留时间比较长的情况是:当用户锁屏时,或者系统提示用户去响应某些(诸如电话来电、有未读短信等)事件的时候。3、Active激活:当前应用正在前台运行,并且接收事件。这是应用正在前台运行时所处的正常状态。4、Backgroud后台:程序在后台而且能执行代码,大多数程序进入这个状态后会在在这个状态上停留一会。时间到之后会进入挂起状态(Suspended)。经过特殊的请求后可以长期处于Backgroud状态。5、Suspended挂起:程序在后台不能执行代码。系统会自动把程序变成这个状态而且不会发出通知。当挂起时,程序还是停留在内存中的,当系统内存低时,系统就把挂起的程序清除掉,为前台程序提供更多的内存
iOS面试题:Autorelease的原理 ?
ARC下面,我们使用@autoreleasepool{}来使用一个Autoreleasepool,实际上UIKit 通过RunLoopObserver 在RunLoop 二次Sleep 间Autoreleasepool 进行Pop 和Push ,将这次Loop产生的autorelease 对象释放 对编译器会编译大致如下:
void *DragonLiContext = objc_ AutoreleasepoolPush();
// {} 的 code
objc_ AutoreleasepoolPop(DragonLiContext);
Delegate和Notification的区别?
并非网络上所说的,简单的一对一和一对多。因为在开源库XMPPFramework 中提供了一个GCDMulticastDelegate 类,使用它可以为一个对象添加多个被委托的对象,那么Delegate 也是可以一对多的。本质区别其实是在使用Delegate 时,你会告诉委托对象去做什么,等他做完之后你再告诉他接着做什么,这是一种命令式的,你需要面对委托者,知道他是谁;而在使用Notification时,你只需要告诉他你要什么,他就给做成了,这是一种响应式的,而且你不需要知道他是谁。
对象的copy与mutableCopy?
[immutableObject copy] // 浅拷贝
[immutableObject mutableCopy] //深拷贝
[mutableObject copy] //深拷贝 ****注意:mutableObject使用copy都是深拷贝***
[mutableObject mutableCopy] //深拷贝
PS:只有不可变对象的copy是浅拷贝,其余都是深拷贝 (是否kai)
GPUImage基本概念
GPUImage 是采用链式方法来处理画面,通过addTarget 方法添加对象到链中。GPUImage 处理环节 source (视频、图片源)-> filter (滤镜)-> final target (处理后的视频、图片)
Cocoapods冲突解决?
方案一、修改podspec里面的dependencies字段的值,可以跟许需要修改platforms,source,source_files,vendored_frameworks,vendored_libraries等等字段的值来避免与其它三方库的冲突。方案二、fork源代码到自己的github帐号下,然后修改代码,引入时采用 pod后面跟上git自己仓库的链接
如何监测内存泄漏的?
可以使用系统的Leaks监测、三方框架(MLeaksFinder)去监测、或者dealloc去监测VC是否被销毁、或者Facebook的开源工具FBRetainCycleDetecto、FBAllocationTracker、FBMemoryProfiler
表视图的滑动卡顿的优化方法?
1、加载网络图片使用异步加载,并缓存;尽量不要设置圆角,采用带圆角的图片;
2、cell的布局填充操作比较耗时,一般创建好久布局好;
3、提前计算cell的高度并缓存cell的属性;
4、尽量使cell的布局大致相同,不同风格的cell采用不同的重用标识符,初始化添加控件,不适用的先隐藏;
5、可以采用局部更新cell的内容;
6、因为渲染耗时较长,尽量使用颜色设置;
7、自定义cell,预先布局好cell的子视图;
8、实现一些必要用到的代理方法;
9、在实现drawRect:的时候,它的rect参数就是需要绘制的区域,这个区域之外的不需要进行绘制。例如可以用CGRectIntersectsRect、CGRectIntersection或CGRectContainsRect判断是否需要绘制image和text,然后再调用绘制方法。
10、在bitmap context里先将其画一遍,导出成UIImage对象,然后再绘制到屏幕。
iOS单元测试框架
XCTest、GHUnit、OCMock
对于代码NSString*nc= [[NSArray alloc] init]; 编译时类型和运行时类型?
编译时是NSString类型,运行时是NSArray类型
iOS导航设计模式有几种?
平铺导航( UITabbarController ) 标签导航( UINavigationController ) 树形导航(UIPageViewController)
iOS中多线程一般有几个方案?
(NSThread, GCD, NSOperation、Pthread)
iOS多线程方案之间的区别?
iOS 如何避免死锁?
我们可以用NSRecursiveLock或者@synchronized替代NSLock
因为NSRecursiveLock或者@synchronized都是递归锁,
递归锁:它允许同一线程多次加锁,而不会造成死锁。
git rebase和git merge的区别
你在一个feature分支进行新特性的开发,与此同时,master 分支的也有新的提交。
此时使用merge如图:
使用rebase(变基)
pod install 和pod update区别
小编之前博客
多个网络请求ABC执行完再执行D,如何设计方案?
1、异步并发(同步任务)
第一种GCD group
dispatch_group_t group = dispatch_group_create();dispatch_queue_t queue = dispatch_get_global_queue(0, 0);dispatch_group_async(group, queue, ^{NSLog(@"同步任务A");});dispatch_group_async(group, queue, ^{NSLog(@"同步任务B");});dispatch_group_async(group, queue, ^{NSLog(@"同步任务C");});dispatch_group_notify(group, queue, ^{NSLog(@"任务完成执行");});
// 2018-04-18 10:18:52.950271+0800 GCD[2283:78081] 同步任务B
// 2018-04-18 10:18:52.950271+0800 GCD[2283:78082] 同步任务C
// 2018-04-18 10:18:52.950273+0800 GCD[2283:78083] 同步任务A
// 2018-04-18 10:18:52.950424+0800 GCD[2283:78082] 任务完成执行// 2018-04-18 10:19:30.821003+0800 GCD[2315:79354] 同步任务B
// 2018-04-18 10:19:30.821003+0800 GCD[2315:79355] 同步任务A
// 2018-04-18 10:19:30.821003+0800 GCD[2315:79370] 同步任务C
// 2018-04-18 10:19:30.821145+0800 GCD[2315:79355] 任务完成执行
第二种dispatch_barrier_async
dispatch_queue_t queue = dispatch_queue_create(0, DISPATCH_QUEUE_CONCURRENT);dispatch_async(queue, ^{NSLog(@"任务A");});dispatch_async(queue, ^{NSLog(@"任务B");});dispatch_async(queue, ^{NSLog(@"任务C");});dispatch_barrier_async(queue, ^{NSLog(@"阻塞自定义并发队列");});dispatch_async(queue, ^{NSLog(@"任务D");});dispatch_async(queue, ^{NSLog(@"任务E");});
自己创建并发队列,然后再执行barrier函数,前面ABC三个任务随机,后面DE随机,但是DE的执行必须是等待ABC任务执行完的
第三种NSOperation
NSBlockOperation *operatioon1 = [NSBlockOperation blockOperationWithBlock:^{NSLog(@"任务A");}];NSBlockOperation *operatioon2 = [NSBlockOperation blockOperationWithBlock:^{NSLog(@"任务B");}];NSBlockOperation *operatioon3 = [NSBlockOperation blockOperationWithBlock:^{NSLog(@"任务C");}];NSBlockOperation *operatioon4 = [NSBlockOperation blockOperationWithBlock:^{NSLog(@"任务D");}];[operatioon4 addDependency:operatioon1];[operatioon4 addDependency:operatioon2];[operatioon4 addDependency:operatioon3];NSOperationQueue *queue = [[NSOperationQueue alloc] init];[queue addOperations:@[operatioon1,operatioon2,operatioon3,operatioon4] waitUntilFinished:YES];NSLog(@"完成之后的操作");
通过任务之间的依赖关系执行,最后的参数YES的时候是会阻塞当前线程,执行完之后再往后执行,NO的话就不阻塞。
iOS为什么使用久了不卡?
iOS的内存回收机制IOS采用引用计数算法回收内存,当对象引用计数为0时,对象会执行反初始化方法并被回收。如果两个对象互相引用对方,就会造成循环强引用,导致内存泄漏。
代码规范: