PS:面试题内容来自群友收集分享,非本人!!!
真实面试题
load方法调用顺序、调用superLoad会走到谁?
总结:
- 1.父类先于子类调用;
- 2.类先于分类调用;
- load调用时机比较早,当load调用时,其他类可能还没加载完成,运行环境不安全;
- 4.load方法是线程安全的,它使用了锁,我们应该避免线程阻塞在load方法;
- 5.load是根据函数地址直接调用的,与类在Compile Sources中的顺序一致;
- 6.load方法通常用来进行
Method Swizzle
;
PS: 调用superLoad, 走消息转发流程
KVO 没有setter
- _NSSetValueAndNotify
atomic
- 非线程安全,仅能保证进入set、get方法是线程安全的
Barried和group
- 栅栏和组,
- 栅栏只能阻拦同步任务
- group可以处理异步任务
target project workspace scheme configuration
- (workspace -> project -> target -> scheme -> configuration) 包含关系
autoreleasePool
绘制完成后下次runloop还绘制么
- 是否绘制取决于UIKit是否认为他是dirty
二叉树深度
- 递归,如果有,则深度+1 取左右子树最大深度
锁
- 自旋锁忙等待, 优先级反转 高优先级占用时间片,低优先级任务无法抢占时间片,任务完不成,不释放资源
- 互斥锁
- 递归锁 统一线程可以重复获取递归锁
- synchronized 性能最差 是递归锁
- 找到obj对应的syncData结构进行加解锁
设置一个单写多读的数据库,要考虑什么(setter如何加锁,同时getter如何高效)
- 并发队列
- 写异步dispatch_barried_async
- 读同步并发队列
App卡顿检测
- runloop监测beforeSource -》 beforeWaitting 的间隔
- 每次runloop CallBack的时候信号量释放,while循环里wait,使用的是信号量的超时机制(如果等待的时间大于设置的时间则直接执行, 超时信号量则返回的是非0
- afterWaitting之后
如何设计一个图片异步加载框架
- api简洁易用
- 任务优先级
- 下载器
- 取消之前任务
- 解码
- 缓存策略
- 缓存过期策略LRU(双向链表配合hash表,key为URL value为node节点)
IM如何解决启动消息堆积问题
- 缓冲池缓存 空闲时处理,或者间隔多久处理一次
- 合并处理
数据库事务的好处
- 原子性 (要么全执行 要么全不执行)
- 隔离性(各个事务是隔离的,互不影响)
- 一致性(事务完成时,数据保持一致状态)
- 持久性 (事务一旦提交,对数据的改变是永久性的)
浏览器输入网址后的过程
- dns解析,
- 三次握手后 https交换密钥,
- 然后正常请求
中间人攻击
swift可选类型如何实现?
- wrapper
http2.1 (多路复用)
HTTP滑动窗口、流量控制
- 报文中有窗口字段,窗口为0时发送方停止发送数据
- 防止接收方缓存区快满了,发送方还在发送数据
- 发送方的发送窗口大小不能超过接收方的给出的窗口大小
Isa
- 实例对象 isa指向类,
- 类对象的isa指向 metaclass
单链表翻转
-
递归
def reverseList(self, head: ListNode) -> ListNode: # 1. 递归终止条件 if head is None or head.next is None: return head p = self.reverseList(head.next) head.next.next = head head.next = None return p
性能检测
- CPU
- FPS
- 卡顿检测(利用runloop 和 信号量超时机制)
SDWeb 然后一个带图片的列表,用sd展示,譬如第二和第四是同一个链接,这种情况下它的策略是什么
- 查找队列任务,并把回调放在同一张图片operation的回调中
- download operation存储着对同一张图片的回调block
tcp拥塞控制,
- 慢开始
- 拥塞避免
- 快重传
- 快恢复
加密
- MD5
- SHA256
- Hash
- AES
gcd里的group,enter,leave,notify作用,
- enter 开始执行任务了
- leave 我执行完成了
- notify 是获取当前组里的任务都完成了,不过要注意notify的位置
方法缓存cache怎么查找的
- 快查
- 慢查
- 填充缓存
MachO的方法列表排序
- 类加载的时候,先是把类中的方法排序然后加到类的方法数组后面,然后到分类时也是先把分类方法排序,再加到类方法数组的前面。
- 分类中的方法地址比原始类中的方法地址要小,这样便能能保证方法列表是有序的,所以能用二分查找
weak的原理,
- weak_table_t
项目结构,组件化分层
- 地基层(第三方依赖以及工程的基础库)
- 基础通用组件(对第三方库的封装以及异常上报,推送服务、支付)
- 基础UI组件
- 基础功能组件(登录注册这种不依赖业务的组件)
- 业务组件
- 更小的业务模块
- 壳工程
查找冲突怎么实现的, 线上日志 崩溃
埋点这些
- 无痕埋点 aop
swift struct 和 class 区别
- 默认创建构造器,
- 值类型和引用类型,
- 继承,
- class堆,
- struct栈,
- 线程安全
- struct更轻量
mutating 关键字
- @inout 传递引用修改
WebView优化
- 包缓存,
- 空白webview常驻缓存,
- 使用wk
swift 派发机制
- 函数表派发,
- 动态派发,
- 直接派发
optinoal怎么实现的
- (struct wapper)
protocol 怎么实现optional
- (@objc)
swift访问权限修饰符
- private
- public
- fileprivate
- protect
上传1个G的大文件,怎么设计,上传的时候读取到内存,一定是一次性读完吗
- 分段读取,NSFileHandler
微信通话,让你设计,用TCP 还是 UDP,为什么
- udp, 视频通话丢包可以接受,
UDP发送1、2、3、4、5,5 个数据包,怎么保证它的顺序
- 协议中添加包的编号,接受包的时候排序
冷启动runtime的初始化调用哪些方法
编译器运行原理
- 词法分析,
- 语法分析,
- 语义分析,
- 中间代码生成,
- 中间代码优化,
- 目标代码生成,
- 符号表管理,
- 出错管理
runloop应用场景,
- 监控卡顿,
- 线程保活,
- timer滑动停止
AOP,函数式等等区别,
runtime应用
- 动态添加属性和方法,
- 方法交换,
- 获取和修改私有属性和方法
- 字典转模型
怎么hook+load
- 制作动态库
- 优先编译
内存管理机制
- ARC
- MRC
内存分区以及堆区栈区区别,对象存哪里
- 指针在栈区 325
- 对象在堆区
- 堆、栈、全局、代码、数据
block值捕获,
从点击应用图标开始的app启动流程(系统为程序启动做好准备,
Runloop作用以及如何监测卡顿
- (beforeSource -> waitting 大于阈值, 子线程监听,dump出调用栈)
KVO原理以及自己如何实现
自动释放池相关,譬如何时释放、实现原理、@autoreleasepool加for循环情况下何时释放
深copy与浅copy
- (浅拷贝 拷贝指针)
KVC原理 之后是Key与keypath区别,然后定义一个属性_name 然后kvc通过setValueforkey,这时赋值是用key赋值还是keypath
- keyPath 可以通过路径查找
- 都可以
消息发送原理 然后消息转发为啥要分三个阶段,苹果这样设计的意义在哪儿(字节)
- 第一阶段为动态添加方法
- 第二阶段为替换接收方
- 第三阶段为完全消息转发(有invocation对象,可以实现多次转发,转发给多个对象)
输入法要加载大量表情这时引起内存激增,这种情况如何优化
- 如图大 imageIO进行缩放
- 按需加载
- 如不需要常驻内存,去掉内存缓存
- 如本地图片,使用autoreleasepool包裹加载
事件响应链如何寻找fitview(有次回答了事件响应链的hittest、pointinside方法寻找以及后边touchebegan之类的方法判定后,又这样问我有些懵逼)(字节、小红书、携程都有问)
tcp/udp区别
- tcp 可靠、一对一、流量控制和拥塞控制、面向连接、首部开销大
- udp 不可靠,可一对一、一对多、多对一、多对多、无流量控制和拥塞控制、首部开销小
strong 、weak、copy 、assign 、retain 、unsafe_unretained 与autoreleasing
- autoreleasing当前autoreleasepool作用域内有效,出去即销毁
- 对不可变对象执行
copy
操作,是指针复制,执行mutableCopy
操作是内容复制。 - 对可变对象执行
copy
操作和mutableCopy
操作都是内容复制。
https原理
- Client Hello: Random1、SSL version、 加密套件
- Server Hello:Random2、server选择的加密套件
- Certificate:server让客户端校验证书
- Certificate Verify:client通过证书加密Random3
- Client Key Exchange: server和client用同样的算法加密 random1、2、3即为通讯秘钥
websocket原理
- 利用http协议握手
- 利用tcp来传输数据,请求头小
runloop与autoreleasepool关系
- 线程与runloop一一对应
- autoreleasepool依赖runloop来工作
weak实现原理
- 调用 objc_release
- 因为对象的引用计数为0,所以执行 dealloc
- 在 dealloc 中,调用了 _objc_rootDealloc 函数
- 在 _objc_rootDealloc 中,调用了 object_dispose 函数
- 调用 objc_destructInstance
- 最后调用 objc_clear_deallocating,详细过程如下:
- a. 从 weak 表中获取废弃对象的地址为键值的记录
- b. 将包含在记录中的所有附有 weak 修饰符变量的地址,赋值为 nil
- c. 将 weak 表中该记录删除
- d. 从引用计数表中删除废弃对象的地址为键值的记录
Swift与OC区别 以及swift安全性体现
- 文件个数和后缀不同
- 不需要main函数
- 会自动推导类型
- bool类型明确
- 可以不继承任何类
- final修饰不能被其他类继承
- guard
- inout
逃逸闭包与非逃逸闭包
- 闭包调用时的时机划分为逃逸闭包和非逃逸闭包
gcd如何取消线程
- 线程是由系统管理的,不需要手动管理
- 如果问的是取消任务的话,可以cancel掉未执行的任务
app保活
- backgroundTask
- 持续定位
- 播放无声音频
- 后台下载资源
- BGTaskScheduler
深拷贝和浅拷贝
- 对数组等集合类app进行深拷贝,其内容不变
- 因为数组里存的只是内容的指针,并非本体
启动优化
内存管理,关键字 weak释放
category加载 消息机制(方法查找)
setNeedLayout和layoutIfNeed
UIView性能问题(卡顿掉帧)
- 离屏渲染
- 主线程执行耗时操作
- 大图优化
- tableview优化
- 图层过于复杂
SD 解码
- 已经解码过
- 动图不解码
- 矢量图不解码
组件化分层
看过哪些源码
音视频遇到过哪些问题
im丢消息怎么处理
多线程的应用
YYWebImage和SD 异同点
- 相同点
- category扩展
- 缓存&解码
- 不同
- YY URLConnect
- sd URLSession
- 解码(yy可控制,sd不能控制)
腾讯1面
Block
- StackBlock
- GlobalBlock
- 不会访问任何auto变量
- MallocBlock
kvc与kvo
+load 和 +initialize(有什么注意)
- load由runtime通过函数指针直接调用,无需调用super
- initialize有msgsend调用,存在方法查找,子类不实现,父类可能会调用多次
Catagory 和 extension
commbine
- 响应式
- publisher,
- subscripter,
- subject,
- operator
method swizzling
- 注意事项
- 1.hook次数,
- 2.hook父类导致调用顺序错乱
- 3.很难追查问题
application生命周期
- 启动程序
- willFinishLaunchingWithOptions
- didFinishLaunchingWithOptions
- applicationDidBecomeActive
- 按下home键
- applicationWillResignActive:
- applicationDidEnterBackground:
- app在后台状态,点击app打开
- applicationWillEnterForeground:
- applicationDidBecomeActive:
腾讯二面
工作经历
编译优化
多继承
- oc/swift不支持多继承
- 使用协议模拟
ARC MRC
weak 线程安全?
- 线程安全,每次获取weak指针都会通过objc_loadWeakRetained这个函数
- 判断其是否为tagged
- 加锁并取值
浮点数相等
- NSDecimalNumber,
- 或在已定误差范围内认为其相等
性能监测
- CPU
- 内存 使用量or泄漏
- FPS
- 卡顿检测
- 网络
- crash检测
- 耗电量监控
- 启动时间
断点
- 符号断点
- 条件断点
离屏渲染
TCP UDP
头条1面
sona优化
- 代码过于复杂
- 函数代码行数过多
- switch case条件过多
- if else嵌套严重
- C参数未 release
Flutter与Lua
- 异同点
- Flutter
- 三棵树
- Widget 存储渲染信息
- Element 元素树,渲染实体
- RenderObject 管理布局和绘制
- 三棵树
路由方案及事件总线
- protocol
- URL
包体积优化
- 无用图片、类、资源等,压缩图片
- 减少动态库数量
- 减少无用依赖
- 去除无用架构
- xcode默认配置的编译参数
App启动过程
runloop及应用
- 卡顿检测
搜狐一面
sd用了哪些锁
- synchronized
锁的性能排行
- synchronized 最差
- os_unfair_lock 最好
synchronized原理
- objc_sync_enter
- objc_sync_exit
- 锁对象只能是同一个
- 可重入型互斥锁
afn线程保活
- afn各版本的区别
- 2.0有线程保活,基于URLConnection,回调只能回调给原runloop
- 3.0不需要 URLSession可以指定回调队列,NSOperationQueue设定max为1,让回调串行执行
伪代码设计单写多读
runloop source0和1分别都对应什么事件
- source 1 系统级别的事件
- source 0 是程序员处理的任务
点击btn是如何事件传递唤醒runloop
- 包装event -> source1 -> mach_port唤醒runloop -> source0
runloop和线程的关系
- 关系存储在全局字典里 线程key runloop是value
- 一一对应
runloop有多少个mode 多少个status、
- kCFRunLoopBeforeTimers
- kCFRunLoopBeforeSources
- kCFRunLoopBeforeWaiting
- kCFRunLoopAfterWaiting *
- kCFRunLoopExit
@synthesize 和 @dynamic
- 如果没有手动实现将为属性自动生成getter和setter方法
- dynamic 告诉编译器不要自动生成setter和getter
NSString类型为什么要用copy修饰
- 对NSString来说没影响
- 对NSMutableString来说有,防止被修改
多线程实现方式以及优缺点(gcd对比NSOperation)
- GCD是C语言, 所以效率更高, operation获得更好的依赖、优先级、kvo等优点
- operation 是对GCD的高层次抽象
- 依赖关系,operation可以设置依赖,gcd不行,可以用其他方法
- operation可以kvo
NSTimer循环引用
- 使用block的形式
- 使用NSProxy
- iOS13+新API
block类型 以及循环引用
- stackBlock
- mallocBlock
- globalBlock
如何优化启动时长
- 管理启动项
- load方法清理
- 减少动态库
- 减少类的数量
extension和category的区别
- extension在编译期间, 可新增成员变量,是类的一部分,无法为系统类添加extension
- category在运行期间,不能添加成员变量
autoreleasepool分别在哪些情况下会释放
- runloop即将进入休眠时
- 出pool作用域
- 线程被释放
autoreleasepool底层原理,
- 双向链表
- runloop enter的时候会push, exit会pop
- runloop 在即将休眠时先pop 然后再push
weak实现原理
解压zip遇到过哪些问题
- 中文文件名乱码
webview加载优化
autorelease 和 runloop的关系
- 注册了entry来push 优先级最高,优先执行
- 监听beforeWaiting来pop和push 优先级最低,保证最后执行
webview桥接怎么做的
说说Swift为什么将String,Array,Dictionary设计成值类型
- 值类型相比引用类型,最大的优势在于内存使用的高效
- 线程安全考虑
MachO结构
- Header(包含文件类型、目标架构类型等)
- Load Commands(文件在虚拟内存中的逻辑结构、布局)
- segment(segment约定使用双下划线加大写字母,例如
__TEXT
)- section(section约定使用双下划线加小写字母,例如:
__text
)
- section(section约定使用双下划线加小写字母,例如:
MachO Segment
-
__TEXT
段包含代码,它被以只读和可执行的方式映射,即进程可以执行代码,但不能修改代码。代码也不能修改自身,因此,page永远不会dirty。
-
__text
section包含编译好的机器码。 -
__stubs
和__stub_helper
section用于动态链接器(dyld),这样链接动态链接代码时,可以延迟链接 -
__const
其是常量; -
__cstring
包含可执行文件中字面量字符串。
-
-
__DATA
段是可读可写的,但不能执行,包含可被更新的值。-
__nl_symbol_ptr
是非懒加载符号指针,在可执行文件加载时就已经加载了 -
__la_symbol_ptr
是懒加载符号指针,用于调用可执行文件中未定义的符号 -
__const
:包含一些需要重定向的常量数据。如char * const p = "foo";
被p
指针指向的数据不是常量。 -
__bss
:包含未初始化的静态变量。如static int a
。 -
__common
:包含未初始化的外部全局变量。如函数外的int a
。 -
__dyld
:是占位section,用于动态链接器。
-
网友评论