iOS面试题总览
文章平均质量分 74
收集各类iOS底层面试题,整理收集,形成自己的iOS技术知识架构图!
神经骚栋
IT界无底坑洞栋主
展开
-
01-OC对象占用内存大小
例如 如果一个继承于NSObject的类有且只有一个CGRect属性,由于CGRect是结构体,最终由 4个 CGFloat类型构成,那么就是32个字节,再加上isa指针的8个字节,由于都是8字节数据类型,进行内存对齐法则之后,依然是8个字节,故最终占用40个字节,然后还要根据是16字节的倍数,所以这个对象最终开辟48个字节.是返回成员变量的大小,并非结构体本身的大小,NSObject成员变量有且只有一个isa指针,所以只有8个字节.源码可以查询到开辟空间规范限制,如下所示.使用如下方法发现,字节数是。原创 2023-03-19 23:18:43 · 198 阅读 · 0 评论 -
02-iOS对象的本质
类对象主要存储的内容含有 isa指针、superclass指针、类的属性列表信息、类的对象方法列表、类的协议信息以及类的成员变量信息等.每个类内存中有且只有一份类对象.iOS对象大致可以分为3类,分别是实例对象(instance-object)、类对象(class-object)、元类对象(meta-class-object).元类对象主要存储的内容含有 isa指针、 superclass指针、类的类方法列表.每个类内存中有且只有一个元类对象.实例对象主要存储的是 isa指针、成员变量的值信息.原创 2023-03-19 23:21:12 · 105 阅读 · 0 评论 -
03-isa指针与superclass指针
NSObject的meta-class对象 superclass指针并非指向于nil,而是指向于NSObject的class对象.isa指针在arm32位直接存储的内容就是class或者meta-class地址信息.大部分meta-class和class对象的superclass指针指向于父类.所有的meta-class的isa指针指向于root-meta-class.class对象的isa指针是指向于meta-class对象.instance对象的isa指针指向于class对象.原创 2023-03-19 23:21:58 · 79 阅读 · 0 评论 -
04-class类对象的底层结构
objc_class结构体继承于objc_object结构体,objc_object结构体有且只有一个isa指针.注:在最新的objc818.2的代码结构,已经把相关成员变量实现已经直接修改为函数.相关成员变量已经存在了。objc_class 含有一个 cache_t类型的 cache成员变量,主要作用是方法缓存.objc_class 含有一个 class_data_bits_t类型的 bits.objc_class 含有一个 Class类型的 superclass成员变量.宏进行了一次与运算.如下所示.原创 2023-03-19 23:20:30 · 58 阅读 · 0 评论 -
05-KVO的实现过程
当在iOS中对一个对象添加KVO时,实际上runtime会在原来的类基础上生成一个派生类。, 该类中重写了监听属性的set方法. 被监听的对象的isa指针会指向该派生类.直接赋值成员变量不会触发KVO,KVO的本质可以认为是调用派生类的属性Set方法.赋值成员变量不能触发Set方法,所以不能触发KVO.当然了,除了上述方法,还有其他方法的做了一些修改.在Set方法中调用了Foundation框架中。方法,内部实现主要有三方面。原创 2023-03-19 23:24:21 · 93 阅读 · 0 评论 -
06-KVC内容相关
顺序去查找成员变量.如果查找到则完成赋值,如果查找不到则依然会调用。四个方法,如果有则进行调用并且返回其值.的返回值,如果为NO,那么直接调用。,如果有,则直接调用方法传入参数.首先先判断是否有属性的Set方法。返回值为YES,那么直接 按照。如果上述查找不到,那么就仍然调用。返回值为YES,那么他会按照。返回值为NO,那么就会调用。KVC的赋值过程会触发KVO.上述方法未找到,则判断。原创 2023-03-19 23:28:20 · 71 阅读 · 0 评论 -
07-Category的内容相关
注: list_array_tt 是 method_array_t、protocol_array_t、property_array_t 的父类.函数,不管是实例方法/类方法/协议列表/编译顺属性列表都是先根据序,构建。的结构体, 在运行时将 方法 属性 协议 动态注入到类对象或者元类对象中.类的 Extension 在编译时相关数据就已经包含在类信息中了.Category 在编译过程中会形成如下所示的。Category在运行时的加载过程,其通过源码。的文件顺序决定,也可以说是由编译顺序决定.原创 2023-03-19 23:29:04 · 56 阅读 · 0 评论 -
08-load、initialize的内容相关
load方法的调用方式是直接通过指针寻找,并非常规的方法调用方式(消息发送机制).所以不存在方法覆盖问题.这一点可以通过源码中。方法是runtime在加载类、分类时自动调用的方法.关于 load 方法的调用顺序主要有以下三点.调用时机是类第一次调用方法时调用的方法.,所以方法调用顺序以及调用过程按照。. 调用顺序可以查看源码中得。的调用顺序是先调用父类的。注: 本问题回答基于。这两个方法进行确认.原创 2023-03-19 23:29:41 · 107 阅读 · 0 评论 -
09-关联对象的内容相关
Category是可以直接添加属性, 因为 category_t 是含有 propert_list_t 类型的 properties 的成员变量结构的.MapStorage 的Key 为objc_object泛型的指针类型. Value 为 ObjectAssociationMap;当然,如果一定要给分类添加属性,可以使用Runtime库中得下面三个关联对象的API来进行实现.但是 Category 添加属性的本质 实际上只是添加的 Set方法 和 Get方法 的。整体结构图如下所示.原创 2023-03-19 23:30:12 · 82 阅读 · 0 评论 -
10-block的内容相关
如果把block复制到堆上时,会调用copy函数,函数内部会调用 __Block_object_assign 函数对其__block生成的结构体进行一次copy处理,把__block变量结构体拷贝到堆上并产生强引用.并且 __block变量结构体内部也会同时调用内部copy函数,根据指针类型来添加强弱引用(PS: 强引用的话,引用计数会 + 1)由于 __block_impl 类型的 impl 是 __main_block_impl_0 中得首页成员变量,所以两者的内存地址是一致的,故可以强转.原创 2023-03-19 23:30:53 · 95 阅读 · 0 评论 -
11-Method调用的相关
在 818.2版本中有 big small 之分,big就是先前传统意义上的三个成员变量.但是对外的表现是一样的,不管是 name, type 还是 imp 现在的实现是通过。super 关键字调用方法只是查找方法的位置从父类开始,但是消息的接受者仍然是当前类.small 则是主要包含了三个偏移指针.个人猜想是用来压缩内存空间的.判断是 big存储结构 还是 small存储结构来进行不同的取值.进行字符串编码生成的, 包含返回值类型与参数类型.方法缓存的过程,主要由以下几个步骤完成.索引变更方法如下所示.原创 2023-03-19 23:29:30 · 57 阅读 · 0 评论 -
12-RunLoop的相关内容
当用户滑动时,主线程的RunLoop处于UITrackingRunLoopMode的模式下,所以想要reloadData不打断用户的滑动操作,那就需要把reloadData的调用放入主线程RunLoop的NSDefaultRunLoopMode.实现一个常驻线程就需要开启线程的RunLoop,同时我们需要给RunLoop添加一个Port/Source事件来维持RunLoop的事件循环(因为RunLoop的mode中一个Item没有,那么RunLoop就会退出).RunLoop的主要流程如下所示.原创 2023-03-19 23:30:11 · 74 阅读 · 0 评论 -
13-多线程的相关内容
打印的线程都是在同一个线程中.打印顺序为 1 → 2 → (栅栏函数打印线程) → (3 4), 大概率为 1 → 2 → (栅栏函数打印线程) → 4 → 3。并发队列 + 添加异步任务 会导致创建新的线程. 当前线程与新线程的执行顺序未知, 所以大概率会先执行 1 → 5 .在新的线程中,同步添加任务打印3,那么不会再次创建新的线程了,只会在当前线程串行执行. 也就是 2 → 3 → 4.串行队列添加异步任务,不会创建新的线程.所以当前是什么线程,那么block中代码执行所在的线程就是什么线程.原创 2023-03-19 23:34:00 · 98 阅读 · 0 评论 -
14-内存管理的相关内容
函数. 函数中会判断当前对象是否是被关联对象,是否含有C++的析构函数,是否被weak修饰过等,这些信息都是通过 ISA 指针来获取.如果上述任何条件都不成立,那么直接调用。每一个 AutoreleasePoolPage 对象占用4096个字节内存,除了存储自身的成员变量外, 剩下的空间用来存储 autorelease 对象的地址. 可以通过。ARM64架构下,如果当前对象曾经被weak指针修饰过,那么它的ISA指针就会。在释放对象的过程中,主要进入的调用的函数是 objc_object 的。原创 2023-03-19 23:35:12 · 73 阅读 · 0 评论 -
15-定时器相关内容
NSTimer的使用范围要广泛的多,各种需要单次或者循环定时处理的任务都可以使用。在UI相关的动画或者显示内容使用 CADisplayLink比起用NSTimer的好处就是我们不需要在格外关心屏幕的刷新频率了,因为它本身就是跟屏幕刷新同步的。NSTimer的精确度就显得低了点,比如NSTimer的触发时间到的时候,runloop如果在阻塞状态,触发时间就会推迟到下一个runloop周期。并且 NSTimer新增了tolerance属性,让用户可以设置可以容忍的触发的时间的延迟范围。原创 2023-03-19 23:37:59 · 82 阅读 · 0 评论 -
16-网络协议相关
DNS请求报文上传到路由器的数据链路层,数据链路层会判断当前报文的目标MAC地址是否自身,如果不是自身,那么就会舍弃该报文,如果报文的目标MAC地址是自身,那么会进行解析,并且传输到路由器的网络层,网络层依然会通过ARP协议请求来获取下一个目标设备的MAC地址,继续网络传输.当DNS请求报文发送到网络运营商这边时,网络运营商就会根据DNS请求报文中的IP地址确认当前DNS服务器是否是当前运营商的DNS解析服务器,如果是,则会发送该DNS请求报文,如果不是,那么会通过网络发送给其他的DNS服务器.原创 2023-03-19 23:38:59 · 113 阅读 · 0 评论 -
17-优化相关
可执行文件和动态库中所有的符号(Class,Protocol, Seletor, IMP …) 都按照格式加载到内存中,被Runtime所管理.main函数就会调用UIApplicationMain函数,Appdelegate中得。dyld 是iOS的动态链接器, 可以用来装载Mach-O文件.所有初始化工作完成之后dyld就会调用main函数.原创 2023-03-20 00:05:12 · 66 阅读 · 0 评论 -
18-weak实现原理相关内容
当对象释放的时候,底层调用的是 rootDealloc() 函数, 如果没有C++的析构函数,没有关联对象,没有weak指针曾经指向过,那么就会通过 free 立马释放该对象. 对于weak,那么其实会进一步调用 clearDeallocating() 函数, clearDeallocating() 会根据对象的地址获取到其对应的weak指针列表, 遍历整个列表把它置为nil, 最后把这个 entry 从全局的weak表中删除.weak相关步骤如下所示.原创 2023-03-20 00:05:43 · 102 阅读 · 0 评论 -
19-离屏渲染相关内容
离屏渲染的过程之所以消耗比较昂贵,其主要原因不在于渲染,而在于缓冲区的创建以及缓冲区上下文的切换过程中,由于离屏渲染会增加GPU的工作量,很有可能导致CPU+GPU的时间间隔超过16.7ms,从而导致页面卡顿.CPU/GPU计算处理时间速度与屏幕刷新时间不一致导致的,也就是显卡输出帧的速度比显示器快,显示器的处理速度跟不上显卡,在显示器处理第一帧的时候,第二帧的缓冲就已经来了,所以就会有屏幕撕裂的问题了.原创 2023-03-20 00:06:17 · 62 阅读 · 0 评论 -
20-响应者链相关内容
重复上面过程,当传递到window时,如果window对象也处理不了响应,那么就会交给UIApplication,UIApplication的delegate也是继承于UIResponder,如果UIApplication的delegate也处理不了响应,那么该响应就会被抛弃.当一个硬件事件(触摸/晃动/锁屏等)发生之后,首先由IOKit.framework生成IOHIDEvent事件,并且传递给SpringBoard,SpingBoard只能接收按键, 触摸, 加速, 接近传感器等几类Event事件.原创 2023-03-20 00:06:58 · 131 阅读 · 0 评论 -
21-组件化相关内容
服务方提前在中间件注册 Protocol - Class, 中间件以Protocol为key, Class为value进行存储保存.调用方以Protocol调用中间件的方法,从而获取Class. 然后再通过创建实例对象,通过实例对象调用协议方法,完成整个调度.服务方提前在中间件注册 URL - Block, 中间件以URL为key, Block为value进行存储保存.调用方以URL形式调用中间件的方法,从而调用Block.服务方不需要再进行注册,调用方通过中间件的方法运用Runtime的。原创 2023-03-20 00:07:32 · 90 阅读 · 0 评论 -
22-Notification相关内容
通过在主线程的RunLoop添加machPort,设置这个port的delegate. 通过这个port, 其他线程可与主线程进行通信. 在这个port的代理方法中执行的代码肯定在主线程中运行,所以在代理方法中 NSNotificationCenter调用post方法即可.通知的发送是同步的,在哪一个线程发送就在哪一个线程接收,并没有开启异步线程.通知的异步发送实际上是利用RunLoop机制进行的延时发送,并不是真正意义上的异步线程发送通知.如果是在主线程中响应异步线程的通知,可用如下的API.原创 2023-03-20 00:06:12 · 123 阅读 · 0 评论 -
23-cocoapods相关内容
Manifest.lock 是 Podfile.lock 的副本,每次只要生成 Podfile.lock 时就会生成一个一样的 Manifest.lock 存储在 Pods 文件夹下。当生成工程完成之后,就需要写入依赖,将依赖更新写入 Podfile.lock 和 Manifest.lock. Podfile.lock 和 Manifest.lock 也是后期版本对比与更新的重要文件. 可以认为 Manifest.lock 是 Podfile.lock的副本文件.原创 2023-03-20 00:08:49 · 329 阅读 · 0 评论 -
24-Flutter相关内容
方法生成的, Element持有了Widget,维护了RenderObject. Element的主要承担把Widget配置转换为RendeObject渲染的作用, Widget是不可变的, Element是可变的, Element实现了类似于React 虚拟Dom Diff 的作用, 把真正需要修改的部分同步到 RenderObject中, 提高渲染效率.的Widget才会真正生成 RenderObject. RenderObject是最终参与渲染的渲染树, 保存着元素的大小,位置等渲染信息.原创 2023-03-20 00:07:22 · 109 阅读 · 0 评论 -
25-动画相关内容
的分工了,presentationLayer其实就是我们看到的展现到屏幕上的视图layer, modelLayer则是管理渲染数据Layer,像我们平常设置frame,color等渲染数据其实并不是直接设置到presentationLayer上,而是设置在modelLayer上.当垂直同步信号来临时,presentationLayer需要渲染的时候,就会去modelLayer中获取渲染数据,然后再进行绘制.所以虽然两者并不是完全同步的,但是肉眼是观测不到的.那么为什么Button在动画过程中无法被响应呢?原创 2023-03-20 00:10:00 · 99 阅读 · 0 评论 -
26-设计模式相关内容
一些基于大话设计模式书籍中的知识提取原创 2023-04-13 05:35:09 · 87 阅读 · 0 评论 -
27-类簇相关内容
常见的类簇有 NSNumber, NSString, NSMutableString, NSArray, NSMutableArray, NSDictionary, NSMutableDictionary 等等.这里要注意的是类簇应该算是是工厂模式(单种产品, 单或多种功能,功能实现不同)的一种特殊实现.而不是抽象工厂模式(应用多种产品, 具有多种类似功能)的一种实现.类簇是一种设计模式,它将一组具有相同功能的类,封装到一个抽象类中,然后通过一个工厂类来创建这些类的实例.原创 2023-04-17 00:28:44 · 102 阅读 · 0 评论 -
28-crash崩溃处理与优化相关
NSTimer的造成的内存泄露并不是循环引用造成的,而是 RunLoop 持有了 NSTimer, NSTimer持有了对象本身造成的,所以不管对象本身是否持有NSTimer都会有一定的内存泄露隐患.答:常见的crash收集工具有很多,比如说: Bugly,友盟,腾讯的Bugly,腾讯的CrashReport,百度的CrashReport,神策的CrashReport等等.我们的思路是这样的,系统最好能主动调起我们写的method swizzling 方法, 这时候就有两种选择,一种是在。原创 2023-04-20 01:17:17 · 275 阅读 · 1 评论