iOS面试题总结(二)
1.instancetype与id的区别与联系
2.NSTimer的使用碰到的问题,如何解决
3.UIViewController的生命周期
4.程序启动的顺序
5.iOS中点击事件的传递
6.JS与OC交互
7.多线程的理解
8.Runtime理解
9.Runloop理解
10.UITableView
(1)cell重用机制原理
(2)UITableView及如何性能优化
11.TCP/UDP协议
(1)TCP为什么是三次握手,四次挥手
(2)UDP丢包原因
(3)TCP丢包,粘包原因,及处理方法
12.静态库与动态库的区别
13.APP瘦身及性能优化
14.SDWebImage原理
13.autoreleasepool原理理解
15.SQL基本语句
16.Https原理
1.instancetype与id的区别与联系
区别1:
在ARC(Auto Reference Count)环境下:
instancetype用来在编译期确定实例的类型,而使用id的话,编译器不检查类型, 运行时检查类型.
在MRC(Manual Reference Count)环境下:
instancetype和id一样,不做具体类型检查
区别2:
id可以作为方法的参数,但instancetype不可以
instancetype只适用于初始化方法和便利构造器的返回值类型
2.NSTimer的使用碰到的问题,如何解决
原因
当你在ViewController(简称VC)中使用timer属性,由于VC强引用timer,timer的target又是VC造成循环引用。当你在VC的dealloc方法中销毁timer,
发现VC被pop,VC的dealloc方法没走,VC在等timer释放才走dealloc,timer释放在dealloc中,所以引起循环引用。
解决
1.使用block来解决
通过创建一个NSTimer的category名字为PFSafeTimer
#import "NSTimer+PFSafeTimer.h"
@implementation NSTimer (PFSafeTimer)
+ (NSTimer *)PF_ScheduledTimerWithTimeInterval:(NSTimeInterval)timeInterval block:(void(^)(void))block repeats:(BOOL)repeats {
return [NSTimer scheduledTimerWithTimeInterval:timeInterval target:self selector:@selector(handle:) userInfo:[block copy] repeats:repeats];
}
+ (void)handle:(NSTimer *)timer {
void(^block)(void) = timer.userInfo;
if (block) {
block();
}
}
@end
2.使用NSProxy来解决循环引用
具体内容见文章iOS之NSTimer循环引用的解决方案
3.UIViewController的生命周期
具体文章内容-UIViewController的生命周期
4.程序启动的顺序
main函数前
系统先读取App的可执行文件(Mach-O文件),从里面获得dyld的路径,然后加载dyld,dyld去初始化运行环境。
开启缓存策略,加载程序相关依赖库(其中也包含我们的可执行文件/动态库),并对这些库进行链接,最后调用每个依赖库的初始化方法,在这一步,runtime被初始化。
当所有依赖库的初始化后,轮到最后一位(程序可执行文件)进行初始化,在这时runtime会对项目中所有类进行类机构初始化,然后调用所有的load方法。最后dyld返回main函数地址,main函数被调用,我们便来到程序入口main函数。
main函数后
①.先加载Main函数
②.在Main函数里的 UIApplicationMain方法中,创建Application对象 创建Application的Delegate对象
③.创建Runloop主循环,Application代理对象开始监听事件
④.启动完毕会调用 didFinishLaunching方法,并在这个方法中创建UIWindow
⑤.设置UIWindow的根控制器
⑥.如果有storyboard,会根据info.plist中找到应用程序的入口storyboard并加载箭头所指的控制器
⑦.显示窗口
5.iOS中点击事件的传递
UITouch
当你用一根手指触摸屏幕时, 会创建一个与之关联的UITouch对象, 一个UITouch对象对应一根手指. 在事件中可以根据NSSet中UITouch对象的数量得出此次触摸事件是单指触摸还是双指多指等等
UIEvent
每产生一个事件, 就对应产生一个UIEvent. UIEvent记录着该事件产生的时间, 事件的类型等等
响应者对象(UIResponder)
在iOS中不是任何对象都能处理事件, 只有继承了UIResponder的对象才能接收并处理事件,我们称为响应者对象
UIApplication,UIViewController,UIView都继承自UIResponder,因此他们都是响应者对象, 都能够接收并处理事件**
iOS中事件的产生和传递
1.发生触摸事件后,系统会将该事件加入到一个由UIApplication管理的队列事件中
2.UIApplication会从事件队列中取出最前面的事件,并将事件分发下去以便处理,通常会先发送事件给应用程序的主窗口(keyWindow)
3.主窗口会在视图层次结构中找到一个最合适的视图来处理触摸事件
hitTest:withEvent:方法
事件传递给窗口或控件的后,就调用hitTest:withEvent:方法寻找更合适的view。所以是,先传递事件,再根据事件在自己身上找更合适的view
**(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent )event **
该方法判断触摸点是否在控件身上, 是则返回YES, 否则返回NO
详情iOS 点击事件传递及响应
6.JS与OC交互
JS调用OC
1.JS与iOS约定好jsTooc方法,用作JS在调用iOS的方法
2.iOS使用addScriptMessageHandler监听JS方法
3.JS通过方法对jsTOoc方法发送消息
4.iOS在- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message 读取name为jsToOc的消息数据messageBody。
OC调用JS
调用方法[self.wkWebView evaluateJavaScript:@“xxxxxxx(js方法语句)”completionHandler:nil];
7.多线程的理解
关于iOS多线程,你看我就够了
8.Runtime理解
runtime的消息转发机制
1.1系统首先找到消息的接收对象,然后通过对象的isa找到它的类。
1.2在它的类中查找method_list,是否有selector方法。
1.3没有则查找父类的method_list。
1.4找到对应的method,执行它的IMP。
1.5转发IMP的return值。
9.Runloop理解
(最全)RunLoop 原理+使用场景+面试总结
10.UITableView
(1)cell重用机制原理
(2)UITableView及如何性能优化
11.TCP/UDP协议
(1)TCP为什么是三次握手,四次挥手
(2)UDP丢包原因
(3)TCP丢包,粘包原因,及处理方法
12.静态库与动态库的区别
静态库在编译的时候会直接拷贝一份目标程序中(会导致目标应用程序的体积增大)
动态库是动态连接方式,编译的时候不会拷贝到程序中,程序运行起来,才会加载。(同一份系统动态库会在iOS系统中被多个程序使用,不会增加单个应用体积)。
13.APP瘦身及性能优化
1.减少可自行文件大小(不用的代码,类文件等)
2.减小工程资源文件大小(图片,音视频文件)
14.SDWebImage原理
15.autoreleasepool原理理解
16.SQL基本语句
select key from table where key = @"xxx"
查找一个班级里面所有男同学名字
select name from student where gender = @"male"
https简要原理
分三步
1.服务端与客户端互相验证证书可靠性
2.服务端与客户端通过非对称加密的方式传输数据加密的密钥(客户端随机生成自负)
3.服务端与客户端利用步骤二产生的密钥进行对称加密数据传输
AP配网与一键配网
AP配网(成功率高,但手机连接设备Wi-Fi麻烦)
设备热点配网,智能硬件处于AP模式(类似路由器,组成局域网),手机用于STA模式
手机连接到处于AP模式的智能硬件后组成局域网,手机发送需要连接路由的ssid和pwd以及自定义的一些信息至智能硬件,智能硬件接收后,找到对应的路由器主动去连接路由器,完成配网。
一键(smartConfig)配网(配网方便,但是成功率低,还要考虑路由器兼容性)
又叫智能配网、快速配网、简单配网。智能硬件处于混杂模式下,监听网络中的所有报文,抓取空口包。手机APP按照一定的协议格式将ssid和pwd及自定义的一些信息编码,以UDP报文格式通过广播包或组播包发送,智能硬件接收到UDP报文后解码,得到正确的ssid和pwd及自定义信息,然后找到对应的路由器主动去连接路由器,完成配网。