# iOS 原生面试题精选
共 250 道,覆盖语言基础、系统原理、
UI、并发、架构、性能、安全、测试与发布。每题都有代码示例、30 秒速记和两组追问。
# 1 Objective-C 语言基础
# 1. 消息发送与动态绑定 的核心机制是什么,工程中应该如何使用?
⚡ 30 秒速记
- 核心结论:先确定 消息发送与动态绑定 的状态所有者、调用线程和生命周期,再讨论
API。 - 运行机制:从
Objective-C语言基础 的入口追踪输入、调度、状态变化和最终可观察结果。 - 工程验证:用最小代码、正常/失败测试和性能工具共同验证,不凭经验猜测。
- 失败边界:重点检查并发竞态、对象销毁、系统回收、版本差异和资源上限。
理解消息发送与动态绑定,关键是追踪对象所有权、运行上下文、状态变化和最终结果,而不是只记类名或回调顺序。 相关工作经过语言、线程、进程或持久化边界时,都要考虑排队、取消、错误传播和资源释放。工程里我会让公共输入可校验、长期任务可取消,并确保 UI 状态回到正确的执行上下文。还要用正常与失败测试及平台分析工具验证,并覆盖对象销毁、系统回收、超时、高负载和版本差异等边界。
讨论 消息发送与动态绑定 时,不能只背类名或回调顺序。首先要确认对象由应用、框架还是操作系统创建,状态保存在哪里,代码在哪个线程或执行器运行,以及进程被回收、页面离开或任务取消后谁负责清理。只有这四个问题明确,API 的使用才不会脱离真实运行环境。
iOS 的运行时会把声明式或命令式代码转换为系统可调度的工作。Objective-C 语言基础 中的更新可能跨越语言、线程、进程、渲染或持久化边界;每越过一次边界,都要考虑序列化、排队、取消、错误传播和资源所有权。面试时应把正常路径画完整,再主动补一个系统回收、非法输入、超时或高负载分支。
下面的最小示例展示与“消息发送与动态绑定 的核心机制是什么,工程中应该如何使用?”同类的生产代码骨架。重点观察输入类型、状态封装和释放位置;示例输出应通过测试断言或平台分析工具确认。
// 消息发送与动态绑定 的核心机制是什么,工程中应该如何使用?
@MainActor
final class UserModel: ObservableObject {
@Published private(set) var user: User?
func load() async throws { user = try await repository.fetchUser() }
}
代码示例刻意省略了产品 UI 和后端细节,但保留了关键不变量:公共输入必须校验,长期任务必须可取消,UI 更新必须回到正确执行上下文,订阅、线程、文件和系统句柄必须随所有者释放。生产实现还要补充结构化错误、日志关联 ID、系统版本分支及正常/失败测试。
💬 面试官追问
-
用户资料页的动态调用在正常导航时工作,但页面退出后回调仍尝试更新
UI;只确认接收对象“能响应消息”为什么还不够?还必须确认对象由谁创建和持有、任务在哪个执行上下文运行,以及页面离开后由谁取消和释放。动态绑定只解决运行时选择目标行为,并不自动处理生命周期;回调越过失效页面边界时,仍可能形成重复更新或资源滞留。
-
资料页的
UserModel.load()通过异步仓库取用户数据,团队希望任意线程收到结果后直接写@Published user;这段实现应守住什么不变量?界面相关状态应在正确执行上下文更新,示例用
@MainActor约束整个UserModel,并把user设为外部只读。异步任务还需支持取消和结构化错误;若页面销毁后任务仍继续,主线程约束本身并不能解决资源所有权问题。 -
同一套消息链从应用对象跨到框架回调,再进入持久化层;每跨一层边界时,你会要求接口补齐哪些约束?
应明确输入能否序列化、工作如何排队和取消、错误怎样向上游传播,以及相关资源归谁释放。边界越多,隐含状态和时序越难推断;若只保留成功回调,超时、非法输入或所有者消失时就容易留下不可恢复的中间状态。
-
线上偶发出现“请求已完成但页面没有更新”,仅在旧系统和快速返回页面时出现;你会怎样缩小消息发送链路的故障点?
先按系统版本、对象标识和关联
ID串联创建、调度、回调、状态写入与释放日志,再复现页面退出和任务取消。重点核对接收对象是否仍存活、回调是否进入正确执行上下文;若缺少失败日志,只能看到结果丢失,无法区分取消、错误传播中断或状态覆盖。 -
业务方要求所有消息都统一切到主线程以避免竞态,性能负责人担心页面卡顿;你会如何拆分执行位置?
只把必须触碰
UI或其可观察状态的更新放到正确的主执行上下文,耗时工作仍应留在适合的任务或执行器中。统一切主线程虽然简化部分时序,却会扩大阻塞风险;拆分后则必须明确状态所有权、取消路径和跨边界错误传播。