2019高级面试知识篇
前言:经过一个星期的面试、总结下这几天面试遇到的问题以及做一次归纳总结、以便日后复习、也便于大家学习和鉴别指正。如有不对请指出一起学习。
Define和Const的区别?
A: Define 不能调试,Const 常量可以调试.
B: Define 在预处理阶段进行替换,Const 常量在编译阶段使用.
C: Define 定义的常量在替换后运行过程中会不断地占用内存,而 Const 定义的常量存储在数据段只有一份 Copy,效率更高。
Static的作用?
A : static修饰的函数是一个内部函数,只能在本文件中调用,其他文件不能调用
B: static修饰的全部变量是一个内部变量,只能在本文件中使用,其他文件不能使用
C: static修饰的局部变量只会初始化一次,并且在程序退出时才会回收内存
Socket的粘包是如何处理的? 一般有2种方法。
注意和服务器确定数据头的定义格式问题,
第一种就是服务器返回的字段中有可识别的头和尾,我们可以根据可识别的头和尾来拆包。
第二种是服务器返回的数据只包含头,头里面有数据的长度,我们可以根据这个头包含的数据长度来进行拆包。本文采用的便是第二种方案。
NSArray与NSMutableArray用Copy修饰还是Strong?
一:NSMutableArray 被copy、strong修饰后的变化:
使用Copy:
把NSMutbleArray使用Copy修饰时有时候回产生Crash,因为对这个数组进行了增删改操作,而copy后的数组变成了不可变数组NSArray,没有响应的增删改方法,所以对其进行增删改操作就会报错。
使用Strong:
如果是strong,直接是赋值a = b;右边是什么,左边就是什么,并且是强引用新值,左边的类型会与右边的相同,不会改变。
二、NSArray 被copy、strong修饰后的变化:
使用Strong:
被strong修饰之后,由于只是强引用,所以副本对象数组和源对象数组只是指向同一个内存区域,这样就会造成副本对象数组会随着源对象数组的改变而改变,即便有时候你并不想让副本对象跟着改变。
使用Copy:
被copy修饰之后,源对象数组被copy了一份,源对象数组和副本对象数组是不同的,所以副本对象数组并不会随着源对象数组改变。
听听大神怎说:iOS内存管理NSArray与NSMutableArray用copy修饰还是strong
Runtime底层实现、有几个指针
可听听大神怎么说的:Runtime详细解说
有3个指针、分别是 isa、IMP、SEL
什么情况下回导致离屏渲染性能问题并且如何处理?
重写drawRect方法,设置圆角、阴影、模糊效果,光栅化都会导致离屏渲染。
设置阴影效果是加上阴影路径。
滑动时若需要圆角效果,开启光栅化。
如何处理如下
一:设置UIView、UITextField、UITextView等大部分控件设置圆角及背景颜色的时候该考虑一下设置方式
通过layer的方式设置 label.layer.cornerRadius =10.f;
通过layer的方式设置 label.layer.backgroundColor = [UIColorwhiteColor].CGColor;
二:对于UIButton、UIIMageView使用DrawInRect绘制UIImage圆角,参考代码
UIBezierPath*bezierPath = [UIBezierPathbezierPathWithRoundedRect:rect cornerRadius:cornerRadius];UIGraphicsBeginImageContextWithOptions(rect.size,false, [UIScreenmainScreen].scale);CGContextAddPath(UIGraphicsGetCurrentContext(), bezierPath.CGPath);CGContextClip(UIGraphicsGetCurrentContext());[selfdrawInRect:rect];CGContextDrawPath(UIGraphicsGetCurrentContext(), kCGPathFillStroke);UIImage*image =UIGraphicsGetImageFromCurrentImageContext();UIGraphicsEndImageContext();
iOS中的方法Methond执行过程?
1:根据对象的isa指针找到类对象id,在查询类对象里面的methodLists方法函数列表查找,如果没有,
2:在沿着superClass,寻找父类,再在父类methodLists方法列表里面查询,最终找到SEL,根据id和SEL确认IMP(指针函数),在发送消息;
iOS浅拷贝、深拷贝的意义和区别?
1、浅拷贝
浅拷贝就是对内存地址的复制,让目标对象指针和源对象指向同一片内存空间,当内存销毁的时候,指向这片内存的几个指针需要重新定义才可以使用,要不然会成为野指针。
计数器是这样的: 浅拷贝就是拷贝指向原来对象的指针,使原对象的引用计数+1,可以理解为创建了一个指向原对象的新指针而已,并没有创建一个全新的对象。
2、深拷贝
深拷贝是指拷贝对象的具体内容,而内存地址是自主分配的,拷贝结束之后,两个对象虽然存的值是相同的,但是内存地址不一样,两个对象也互不影响,互不干涉。
计数器是这样的:深拷贝就是拷贝出和原来仅仅是值一样,使原对象的引用计数保存原理一致,但是内存地址完全不一样的新的对象,创建后和原对象没有任何关系。
3、总结:
深拷贝就是内容拷贝,浅拷贝就是指针拷贝。本质区别在于:
是否开启新的内存地址
是否影响内存地址的引用计数
介绍下iOS网络HTTP、TCP、UDP、Socket 的知识
短连接和长链接的概念及使用场景
短连接:
连接 -> 传输数据->关闭连接。就建立一次,但任务结束就中断连接,安全性高。
使用场景:WEB网站的http服务一般都用短链接。
长连接:
连接 -> 传输数据 -> 保持连接 -> 传输数据。。。-> 关闭连接。是指连接后不管是否使用都保持连接,但安全性较差。
使用场景:长连接多用于操作频繁,点对点的通讯,而且连接数不能太多的情况下。
如何断开长连接:
1:设置timeout=20网络异常时间,表示这个TCP通道可以保持20秒。
2:设置最大请求数量max=XXX,表示这个长连接最多接收XXX次请求就断开。
3:服务端可能主动发起四次握手断开TCP连接,客户端能够知道该TCP连接已经无效;
4:发送心跳包来检测当前连接是否还活着来断开连接
HTTP:http协议即超文本传送协议,是web联网的基础,也是手机联网常用协议之一,http协议是建立在tcp协议之上的一种应用。
http连接最显著的特点是客户端发送的每次请求都需要服务器回送响应,在请求结束后,会主动释放连接。从建立连接到关闭连接的过程称为“一次连接”。
1:在HTTP 1.0中,客户端的每次请求都要求建立一次单独的连接,在处理完本次请求后,就自动释放连接。
2:在HTTP 1.1中则可以在一次连接中处理多个请求,并且多个请求可以重叠进行,不需要等待一个请求结束后再发送下一个请求。
Socket:套接字(socket)是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元。建立Socket链接需要客服端(ClientSocket)和服务端(ServerSocket)组合才能建立完成。
Socket的连接过程分为三个步骤:服务器监听,客户端请求,连接确认。
服务器监听:服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态,等待客户端的连接请求。
客户端请求:指客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。
连接确认:当服务器端套接字监听到或者说接收到客户端套接字的连接请求时,就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,双方就正式建立连接。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。
TCP与UDP的区别
TCP:面向连接、传输可靠(保证数据正确性,保证数据顺序)、用于传输大量数据(流模式)、速度慢,建立连接需要开销较多(时间,系统资源)。
UDP:面向非连接、传输不可靠、用于传输少量数据(数据包模式)、速度快。
TCP三次握手:指建立一个TCP连接时,需要客户端和服务器总共发送3个包。
第一次握手:客户端发送一个TCP的SYN标志位置1的包指明客户打算连接的服务器的端口,以及初始序号X,保存在包头的序列号(Sequence Number)字段里。
第二次握手:服务器发回确认包(ACK)应答。即SYN标志位和ACK标志位均为1同时,将确认序号(Acknowledgement Number)设置为客户的序列号加1以,即X+1。
第三次握手:客户端再次发送确认包(ACK) SYN标志位为0,ACK标志位为1。并且把服务器发来ACK的序号字段+1,放在确定字段中发送给对方.并且在数据段放写序列号的+1。
如何选中TCP还是UDP?
如果是由客户端间歇性的发起无状态的查询,并且偶尔发生延迟是可以容忍,那么使用HTTP/HTTPS。
如果客户端和服务器都可以独立发包,但是偶尔发生延迟可以容忍(比如:在线的纸牌游戏,许多MMO类的游戏),那么使用TCP长连接。
如果客户端和服务器都可以独立发包,而且无法忍受延迟(比如:大多数的多人动作类游戏,一些MMO类游戏),那么使用UDP。
iOS中对象有哪些类型 4种
1:OBJC_ASSOCIATION_ASSIGN = 0,
2:OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1,
3:OBJC_ASSOCIATION_COPY_NONATOMIC = 3,
4:OBJC_ASSOCIATION_COPY = 01403
KVC 和 KVO 的内部实现
KVC内部实现:
1.判断有没有指定key的set方法,如果有set方法,就会调用set方法,给该属性赋值
2.如果没有set方法,判断有没有跟key值相同且带有下划线的成员属性(_key).如果有,直接给该成员属性进行赋值
3.如果没有成员属性_key,判断有没有跟key相同名称的属性.如果有,直接给该属性进行赋值
4.如果都没有,就会调用 valueforUndefinedKey 和setValue:forUndefinedKey:方法
KVC的使用场景
1.动态的取值和设值
2.用KVC来访问和修改私有变量
3.Model和字典转换
4.修改一些控件的内部属性
KVO内部实现:
当某个类的对象在第一次被观察时,系统会在运行时动态创建一个该类的派生类,在该派生类中重写setter方法真正实现通知机制;派生类重写了 class 方法以“欺骗”外部调用者它就是起初的那个类。然后系统将这个对象的isa指针指向这个新诞生的派生类,因此这个对象就成为该派生类的对象了,因而在该对象上对setter的调用就会调用重写的setter,从而激活键值通知机制。此外,派生类还重写了dealloc方法来释放资源。
KVO的使用场景
1:KVO用于监听对象属性的改变。
2:下拉刷新、下拉加载监听UIScrollView的contentoffsize;
3:webview混排监听contentsize;
4:监听模型属性实时更新UI;
5:监听控制器frame改变,实现抽屉效果。
iOS有几种设计模式,每一种设计模式是怎么样的?说一说?
1). MVC模式:Model View Control,把模型 视图 控制器 层进行解耦合编写。
2). MVVM模式:Model View ViewModel 把模型 视图 业务逻辑 层进行解耦和编写。
3). 单例模式:通过static关键词,声明全局变量。在整个进程运行期间只会被赋值一次。
4). 观察者模式:KVO是典型的通知模式,观察某个属性的状态,状态发生变化时通知观察者。
5). 委托模式:代理+协议的组合。实现1对1的反向传值操作。
6). 工厂模式:通过一个类方法,批量的根据已有模板生产对象。
介绍下ViewController生命周期
1.initWithCoder:通过nib文件初始化时触发。
2.awakeFromNib:nib文件被加载的时候,会发生一个awakeFromNib的消息到nib文件中的每个对象。
3.loadView:开始加载视图控制器自带的view。
4.viewDidLoad:视图控制器的view被加载完成。
5.viewWillAppear:视图控制器的view将要显示在window上。
6.updateViewConstraints:视图控制器的view开始更新AutoLayout约束。
7.viewWillLayoutSubviews:视图控制器的view将要更新内容视图的位置。
8.viewDidLayoutSubviews:视图控制器的view已经更新视图的位置。
9.viewDidAppear:视图控制器的view已经展示到window上。
10.viewWillDisappear:视图控制器的view将要从window上消失。
11.viewDidDisappear:视图控制器的view已经从window上消失。
看看其他大神的面试总结 iOS面试题及答案