⚡ Swift基础核心考点解析
在面试的初始阶段,面试官通常会通过考察Swift基础 来评估候选人的语言掌握程度。与Objective-C不同,Swift强调安全性与表达力,以下是几个高频考察点:
📌 Optional 机制
Swift面试题 中必问Optional。它不是简单的指针,而是一个枚举类型。Optional` 等价于 enum Optional { case none, some(T) } 。面试时需解释隐式解包(Implicitly Unwrapped Optional, 如 !)的风险,以及如何使用 if let, guard let 进行安全解包。
📌 值类型与引用类型
Struct是值类型,Class是引用类型。面试常问:为什么Swift默认使用Struct?因为值类型更安全,不存在数据竞争,且性能更优(栈分配 vs 堆分配)。但在需要多态或共享状态时,必须使用Class。
📌 闭包捕获列表
闭包默认强引用捕获变量,易导致循环引用。必须使用 [weak self] 或 [unowned self]。面试重点在于区分 weak (Optional) 和 unowned (非Optional) 的使用场景及崩溃风险。
⚙️ Swift进阶:内存管理与协议
进阶面试不再局限于语法,而是深入底层原理。以下通过选项卡展示三大核心模块:
内存管理
协议与泛型
运行时机制
ARC 自动引用计数详解
Swift使用ARC管理内存。面试常问:循环引用 如何产生?如何解决?
循环引用 :两个对象互相持有强引用,导致引用计数永远不为0。
解决方案 :使用 weak (弱引用) 或 unowned (无主引用) 打破循环。
闭包循环 :在捕获列表中指定捕获语义,如 [weak self] in ...。
// 示例:避免循环引用
class ViewController {
var viewModel: ViewModel?
func setup() {
viewModel?.loadData { [weak self] in
self?.updateUI()
}
}
}
Protocol Oriented Programming (POP)
Swift推崇面向协议编程。与OOP相比,POP更灵活,支持默认实现和组合。
协议扩展 :可以为协议提供默认实现,代码复用性更高。
协议组合 :可以使用 & 组合多个协议,如 where Self: ProtocolA & ProtocolB。
泛型约束 :限制类型必须符合特定协议,增强类型安全。
protocol Networkable {
func request(completion: @escaping (Result) -> Void)
}
extension Networkable {
func printResponse() {
print("Executing network request")
}
}
Runtime 与 Method Dispatch
Swift中有三种方法分发方式:
分发方式
描述
性能
适用场景
Static Dispatch
编译期确定,直接调用
最快
final函数, struct方法
Virtual Dispatch
通过vtable查找
较快
class非final方法
Dynamic Dispatch
通过objc_msgSend查找
最慢
@objc, KVO, 运行时修改
🚀 Swift并发:Actor与Async/Await
Swift 5.5引入的并发模型是近年来的Swift面试题 热点。传统的GCD和OperationQueue逐渐被结构化并发取代。
概念一:Task与TaskGroup
Task 代表一个并发的异步工作单元。使用 TaskGroup 可以管理多个子任务,实现“分而治之”的并发逻辑,例如并行下载多个图片。
概念二:Actor 隔离
Actor 是一种引用类型,用于保护共享状态。与Class不同,Actor内部的状态是串行访问的,天然线程安全。面试常问:Actor与GCD的 async/await 有何区别?Actor更侧重于状态安全,而GCD侧重于任务调度。
概念三:Cancellation
Swift并发支持任务取消。通过检查 Task.isCancelled 或使用 try Task.checkCancellation() 来优雅地处理取消逻辑,避免资源浪费。
// Actor 示例
actor DataStore {
private var data: [String] = []
func add(_ item: String) {
data.append(item)
}
func fetch() -> [String] {
return data
}
}
// 使用
Task {
await store.add("Item")
let items = await store.fetch()
}
🎨 SwiftUI vs UIKit
现代iOS开发面试必然涉及UI框架的选择与对比。
📌 UIKit (命令式)
成熟、稳定、生态完善。使用代码或Storyboard构建UI,状态管理需手动处理。适合复杂交互和遗留项目维护。
📌 SwiftUI (声明式)
未来趋势。代码即UI,状态驱动视图刷新。语法简洁,支持多平台(iOS, macOS, watchOS, tvOS)。学习曲线陡峭,但开发效率高。
📌 混合开发策略
实际项目中常采用混合模式。UIKit中使用 UIHostingController 嵌入SwiftUI视图,或反之。面试需展示对两者共存的理解。
❓ Swift面试高频问答精选
以下整理了网友最关心的Swift面试题 ,并提供了深度解答,总字数涵盖核心知识点,助您全面准备。
Q1: Swift中的 @objc 和 dynamic 关键字有什么区别?
@objc 是一个属性标记,告诉编译器将标记的实体暴露给Objective-C运行时。它并不强制使用动态分发,编译器仍可能进行静态优化(如内联)。
dynamic 是一个方法修饰符,强制使用Objective-C风格的动态分发(Message Sending),即 objc_msgSend。这确保了KVO(Key-Value Observing)和Runtime方法交换(Swizzling)能正常工作。
总结 :如果需要KVO或Swizzling,必须同时使用 @objc 和 dynamic。
Q2: 如何优化Swift启动速度?
启动速度优化是高级开发的必备技能:
1. 减少Main Bundle大小 :移除未使用的资源,使用Asset Catalog。
2. 延迟加载 :非核心库(如Analytics、CrashReporter)使用懒加载或动态库。
3. 优化AppDelegate :避免在 application:didFinishLaunchingWithOptions: 中执行耗时操作。
4. 使用Pre-main Time Profiler :分析启动阶段的方法调用,消除瓶颈。
5. 减少全局变量初始化 :全局变量的初始化会在Main RunLoop之前执行,耗时且不可控。
Q3: Swift中的Error处理与Result类型有何优劣?
do-catch 适合需要立即处理错误并恢复流程的场景,但链式调用不便。
Result<Success, Failure> 是Swift 5.0引入的枚举类型,将成功和失败封装为一个值。优势在于:
1. 适合异步回调和函数式编程。
2. 可以轻易组合和转换。
3. 避免了嵌套的 do-catch 块。
建议 :在API层和ViewModel层使用Result,在UI层使用do-catch。
Q4: 什么是Swift的Copy-on-Write (COW)?
COW是一种性能优化技术,主要用于String, Array, Dictionary等集合类型。当值类型被赋值时,最初共享底层数据,只有当一方尝试修改数据时,才进行深拷贝。这避免了不必要的内存分配和数据复制,提升了性能。