一面
1.属性关键字,在 ARC、MRC下分别用什么关键字,copy 修饰 NSString,可变字符串用什么修饰?block 用什么修饰?能不能用 strong 修饰?assign 能修饰对象吗?unsafe_unretain 有什么作用?
2.block,有几种 block,__weak
__block
,__block
修改局部变量的值原理,只把局部变量变成结构体就可以了吗?
3.多线程都用过哪些?NSOperation 了解吗?GCD 怎么开一个线程
4.什么是死锁,举例说明为什么会死锁
5.内存都有哪些区域?哪些是在栈上,哪些是在堆上?局部变量存在哪里?
6.+load 父类、子类调用顺序?分类的 +load 会调用吗?项目里有用到 +load 吗?initialize
7.Category 实现了本类的同名方法,有没有办法来调用本类的方法?
8.单链表是否有环
9.两个链表是否相交(怎么判断是否相交?怎么找交点)
10.两个字符串的最长相同子串的长度
二面
1.较难定位的 Crash 怎么定位?怎么判断是 OOM 导致的 Crash 还是其他导致的 Crach?
2.Jenkins+Fastlane 实现 CI,自动化的流程除了打包还能做什么?
3.Flutter 和原生开发你觉得有什么差异
4.HTTPDNS,使用和不使用有什么区别?有什么好处?
5.通知是同步的还是异步的,异步的通知什么时候会发出去,通知的原理,通知如何存储,多次添加通知,多次移除通知会有问题吗?
6.屏幕显示的流程,CPU/GPU,离屏渲染是什么?光栅化的过程
7.安装包大小优化做了哪些?段迁移了解吗?
8.App 启动系统做了哪些事情,怎么优化启动速度
9.tableView 滑动流畅性优化
10.从点击屏幕到响应事件的流程
11.UIView 和 CALayer 的关系,为什么要这么设计
12.autoreleasePool 的原理,设计成双向链表有什么好处
13.最有成就感的项目,组件化的好处
14.如果 Code Review,你会关注哪些东西?
15.相对其他团队成员的优势
16.分享会怎么做,如果听众有 PM/测试,会怎么分享
17.团队里有成员不是特别优秀,怎么把控进度
18.了解百度的技术职级吗?你觉得自己是T几?
三面
经理 项目中遇到的有挑战的问题
四面
HR
五面
1.通过什么途径学的包括 Vue 的其他知识?为什么会有前端的需求?
2.IM 的气泡,点九图有没有使用类库,有没有兼容性问题,项目适配的最低系统版本是多少?
3.IM 文本高度计算,图文混排怎么计算高度,高度计算有没有遇到什么问题
4.整个 IM 页面的布局,最复杂的 cell 布局
5.收到新消息的处理,怎么处理能够不滚动到页面底部
6.大量图片列表滑动到指定位置,怎么避免出现内存导致的问题,为什么没有落地
7.组件化,什么能拆成组件,你认为组件化做的足够好吗?更好的组件化怎么去做?
8.你认为 iOS 和其他端有什么不一样,有什么经验可以共用?
9.未来规划
参考答案
一面
1.属性关键字,在 ARC、MRC下分别用什么关键字,copy 修饰 NSString,可变字符串用什么修饰?block 用什么修饰?能不能用 strong 修饰?assign 能修饰对象吗?unsafe_unretain 有什么作用?
nonatomic, readwrite, strong/copy/weak/asign
可变字符串用strong修饰,用copy修饰后就变成了不可变字符串,调用可变字符串的方法会报找不到方法错误
block用copy修饰,也可以用strong
assign不能修饰对象,修饰对象会引用计数不增加,在对象释放后,属性仍然保存之前的地址,访问会变成野指针,导致EXC_BAD_ACCESS,对象用strong或weak修饰
unsafe_unretain 不增加引用计数,不自动置nil,比assign更明确用于对象,但比weak危险。
2.block,有几种 block,__weak
__block
,__block
修改局部变量的值原理,只把局部变量变成结构体就可以了吗?
GlobleBlock 全局block
StackBlock 栈block
MallocBlock 堆block
__weak
用于避免循环引用,block强引用对象时,使用__weak
弱引用打断循环;安全访问:对象被释放后,弱引用会自动置为nil,避免野指针。
__block
用于在block内部修改局部变量的值,普通局部变量在block内部是不可变副本,捕获的是变量的值,用__block
修饰后,block捕获的是对变量的引用。
__block
的内部实现类似:
1 | __Block_byref_count_struct { |
3.多线程都用过哪些?NSOperation 了解吗?GCD 怎么开一个线程
[NSThread currentThread] GCD
dispatch_group_enter dispatch_group_leave dispatch_notify
dispatch_semaphore wait信号量-1 signal信号量+1
(1)可以控制并发数量 初始设置为最大并发数,开始任务wait -1;任务完成signal+1
(2)实现线程同步 初始设置为0,异步任务里加1,wait等待子线程完成
NSOperation是对GCD的封装,可以设置优先级,并发数,依赖关系,取消
GCD异步async有开线程的能力
4.什么是死锁,举例说明为什么会死锁
死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。
四个必要条件
互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。
请求和保持条件:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。
不剥夺条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。
环路等待条件:指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源。
举例:
1 | - (void)viewDidLoad { |
dispatch_sync 同步,阻塞当前线程,即阻塞主线程。block 又在等主线程里的 viewDidLoad 执行完,从而形成了主线程等待主线程,造成死锁。
参考链接:百度百科-死锁
5.内存都有哪些区域?哪些是在栈上,哪些是在堆上?局部变量存在哪里?
代码段(__TEXT
)、数据段(__DATA
)、堆区、栈区、内核区;
代码段:编译后的代码。
数据段:字符串常量、全局变量、静态变量。
栈:局部变量(基本数据类型)和实参
堆:通过alloc、malloc、calloc动态分配的空间。
局部变量指针本身存在栈上,动态分配的对象/内存在堆上
内存区域 | 栈 / 堆 | 内容 |
---|---|---|
栈(Stack) | 栈 | 局部变量、函数参数、返回地址 |
堆(Heap) | 堆 | 对象实例、动态分配内存 |
全局/静态区 | — | 全局变量、静态变量 |
常量区 | — | 字符串常量、字面量对象 |
方法区(Text) | — | 程序代码、类定义、方法实现 |
6.+load 父类、子类调用顺序?分类的 +load 会调用吗?项目里有用到 +load 吗?initialize
+load 父类先于子类,类先于分类。
+load 调用顺序
1.先调用类的 +load
- 按照编译先后顺序调用(先编译,先调用)
- 调用子类的 +load 之前会先调用父类的 +load
2.再调用分类的 +load
- 按照编译先后顺序调用(先编译,先调用)
+initialize方法会在类第一次接收到消息时调用。+initialize 调用顺序:
- 先调用父类的+initialize,再调用子类的+initialize
- (先初始化父类,再初始化子类,每个类只会初始化1次)
7.Category 实现了本类的同名方法,有没有办法来调用本类的方法?
在Category的+load方法中把原类的实现保存起来,在需要使用时直接调用。
1 | #import <objc/runtime.h> |
8.单链表是否有环
1 | function hasCycle( head ) { |
9.两个链表是否相交(怎么判断是否相交?怎么找交点)
1 | function FindFirstCommonNode(pHead1, pHead2) |
10.两个字符串的最长相同子串的长度
题目链接:NC127 最长公共子串
1 | function LCS( str1 , str2 ) { |
二面:
1.较难定位的 Crash 怎么定位?怎么判断是 OOM 导致的 Crash 还是其他导致的 Crach?
2.Jenkins+Fastlane 实现 CI,自动化的流程除了打包还能做什么?
3.Flutter 和原生开发你觉得有什么差异
4.HTTPDNS,使用和不使用有什么区别?有什么好处?
传统DNS: 域名 -> DNS 服务器 -> 返回IP
HTTPDNS: 域名 -> HTTP请求 -> HTTPDNS服务 -> 返回IP
- 移动端直接通过 HTTPS 请求运营商或第三方提供的 HTTPDNS 服务获取真实 IP。
- 避免依赖系统 DNS,有助于解决 DNS 污染、缓存不准确、解析慢的问题。
对比维度 | 使用传统 DNS | 使用 HTTPDNS |
---|---|---|
解析路径 | 系统或运营商 DNS 解析 | 通过 HTTP 请求 HTTPDNS 服务解析 |
安全性 | 易受 DNS 污染、劫持 | 避免污染、劫持,返回真实 IP |
稳定性 | 解析可能失败或返回错误 IP | 高可用、准确 |
解析速度 | 依赖运营商 DNS,可能慢 | 通过 CDN/高速 HTTP 服务,延迟低 |
移动网络体验 | 不同运营商可能解析不同 IP | 可根据客户端地域、运营商精准返回最优 IP |
额外工作 | 无需额外代码 | 需要在请求层或 SDK 集成 HTTPDNS,并可能实现 IP → Host 回填(Host 头) |
(1)防止DNS污染或劫持(2)提升访问速度
5.通知是同步的还是异步的,异步的通知什么时候会发出去,通知的原理,通知如何存储,多次添加通知,多次移除通知会有问题吗?
通知是同步的
- 所有注册了这个通知的观察者方法会立即被调用,调用顺序是按添加观察者的顺序执行的。
- 当前线程会阻塞,直到所有观察者完成处理。
注意:如果你在通知处理方法中执行耗时操作,会阻塞发送通知的线程。
通知的原理:
- iOS 的通知中心 (NSNotificationCenter) 是一个 观察者模式(Observer Pattern)的实现。
- 内部机制:
- NSNotificationCenter 维护一个 字典,key 是通知名 (NSNotificationName) 或者对象 (object),value 是观察者列表。
- 每个观察者存储了:
- 观察者对象(weak 引用,避免循环引用)
- 选择器 (selector)
- 对应通知名和对象过滤条件
- 当发送通知时,中心遍历注册表,找到所有符合条件的观察者并调用其方法。
多次添加,发一次通知,会调用方法两次。多次移除同一个通知没关系。组合问题,添加几次就需要移除几次,否则还会收到通知。
参考链接:iOS-通知中心原理
6.屏幕显示的流程,CPU/GPU,离屏渲染是什么?光栅化的过程
7.安装包大小优化做了哪些?段迁移了解吗?
8.App 启动系统做了哪些事情,怎么优化启动速度
9.tableView 滑动流畅性优化
10.从点击屏幕到响应事件的流程
11.UIView 和 CALayer 的关系,为什么要这么设计
12.autoreleasePool 的原理,设计成双向链表有什么好处
13.最有成就感的项目,组件化的好处
14.如果 Code Review,你会关注哪些东西?
15.相对其他团队成员的优势
16.分享会怎么做,如果听众有 PM/测试,会怎么分享
17.团队里有成员不是特别优秀,怎么把控进度
18.了解百度的技术职级吗?你觉得自己是T几?