一、内存管理与性能优化:从基础到进阶
1.1 循环引用的检测与解决
面试中常考察开发者对循环引用场景的识别能力。例如,在闭包中持有self时若未使用weak修饰,会导致对象无法释放。
示例代码:
class ViewController: UIViewController {private var completion: (() -> Void)?override func viewDidLoad() {super.viewDidLoad()completion = { [weak self] in // 使用weak避免循环引用self?.view.backgroundColor = .red}}}
关键点:需明确weak与unowned的区别,前者在对象释放时自动置为nil,后者会引发运行时错误。
1.2 内存泄漏的排查工具
百度面试官可能要求描述使用Instruments中的Leaks和Allocations工具定位泄漏的步骤。例如:
- 在
Leaks工具中观察内存增长曲线; - 通过
Allocations的堆栈信息定位具体代码位置。
最佳实践:定期在开发阶段运行内存分析,而非仅在测试阶段。
二、多线程与并发编程:核心机制与风险控制
2.1 GCD的死锁场景分析
典型问题:在主队列中同步执行任务会导致死锁。
错误示例:
DispatchQueue.main.sync {print("This will cause deadlock")}
解决方案:
- 异步派发任务:
DispatchQueue.main.async { ... }; - 使用
DispatchWorkItem实现可取消的任务。
2.2 线程安全的数据结构
面试中可能要求实现一个线程安全的队列。常见方案包括:
- 使用
NSLock或@synchronized(Objective-C); -
Swift中推荐
os_unfair_lock或DispatchQueue的屏障机制。
示例代码:class ThreadSafeQueue<T> {private var queue = [T]()private let lock = NSLock()func enqueue(_ element: T) {lock.lock()queue.append(element)lock.unlock()}func dequeue() -> T? {lock.lock()defer { lock.unlock() }return queue.isEmpty ? nil : queue.removeFirst()}}
三、架构设计:模块化与可维护性
3.1 MVC与MVVM的对比
面试官可能要求分析两种架构的适用场景:
- MVC:适合简单界面,但易导致
ViewController臃肿; -
MVVM:通过
ViewModel解耦业务逻辑,适合复杂交互场景。
代码示例(MVVM绑定):
```swift
class ViewModel {
@Published var title: String = “”func fetchData() {
// 模拟网络请求DispatchQueue.main.asyncAfter(deadline: .now() + 1) {self.title = "Data Loaded"}
}
}
class ViewController: UIViewController {
private let viewModel = ViewModel()
private var cancellables = Set()
override func viewDidLoad() {super.viewDidLoad()viewModel.$title.receive(on: DispatchQueue.main).sink { [weak self] title inself?.title = title}.store(in: &cancellables)viewModel.fetchData()}
}
**3.2 组件化与路由设计**百度面试可能涉及模块间通信的方案,例如:- 使用`Protocol-Oriented`设计解耦模块;- 通过`URL Scheme`或`Coordinator`模式管理页面跳转。**关键原则**:避免直接依赖具体类,优先通过接口抽象。### 四、性能优化:从代码到系统级**4.1 列表滚动卡顿优化**常见问题包括:- 单元格高度计算未复用;- 图片加载未异步处理。**解决方案**:- 使用`UITableView.automaticDimension`并预估高度;- 图片加载库(如`Kingfisher`)的异步解码功能。**代码示例**:```swiftfunc tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)let url = URL(string: "https://example.com/image.jpg")cell.imageView?.kf.setImage(with: url) // 假设使用Kingfisherreturn cell}
4.2 离线缓存策略
面试中可能要求设计一个数据缓存系统,需考虑:
- 缓存过期时间(如
TTL); - 磁盘与内存的分级存储。
实现思路:
```swift
protocol Cacheable {
func setObject(_ object: Any, forKey key: String, ttl: TimeInterval?)
func object(forKey key: String) -> Any?
}
class HybridCache: Cacheable {
private let memoryCache = NSCache()
private let diskCachePath = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0]
func setObject(_ object: Any, forKey key: String, ttl: TimeInterval? = nil) {// 内存缓存memoryCache.setObject(object, forKey: key as NSString)// 磁盘缓存(简化版)if let data = try? JSONSerialization.data(withJSONObject: object, options: []) {let fileURL = diskCachePath.appendingPathComponent(key)try? data.write(to: fileURL)}}
}
```
五、系统原理与底层机制
5.1 RunLoop与事件循环
面试官可能询问RunLoop的作用及模式(如NSDefaultRunLoopMode与UITrackingRunLoopMode的区别)。
关键点:
RunLoop是线程的事件处理核心;- 滚动时切换模式可避免卡顿。
5.2 图像渲染流程
需掌握从CALayer到Core Animation的渲染管线,例如:
- 离屏渲染的触发条件(如
cornerRadius+masksToBounds); - 通过
shouldRasterize优化复杂图层。
六、备考建议与面试技巧
- 代码实战:在LeetCode或本地项目中实现典型问题(如二叉树遍历、链表反转);
- 源码阅读:分析
SwiftNIO或Alamofire等开源库的设计; - 模拟面试:与同行进行技术对练,重点训练代码的鲁棒性(如异常处理)。
总结:百度深圳的iOS二面注重技术深度与工程能力的结合,求职者需在掌握基础API的同时,深入理解系统原理与架构设计。通过系统性准备与实战演练,可显著提升通过率。