<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>基础 on Last Stand</title><link>https://amatsuzero.github.io/LastStand/tags/%E5%9F%BA%E7%A1%80/</link><description>Recent content in 基础 on Last Stand</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Mon, 08 Jun 2026 23:06:52 +0800</lastBuildDate><atom:link href="https://amatsuzero.github.io/LastStand/tags/%E5%9F%BA%E7%A1%80/index.xml" rel="self" type="application/rss+xml"/><item><title>App启动流程</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/app%E5%90%AF%E5%8A%A8%E6%B5%81%E7%A8%8B/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/app%E5%90%AF%E5%8A%A8%E6%B5%81%E7%A8%8B/</guid><description>&lt;h2 id="启动类型概览"&gt;启动类型概览&lt;/h2&gt;
&lt;p&gt;iOS应用启动分为三种类型：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;启动类型&lt;/th&gt;
&lt;th&gt;描述&lt;/th&gt;
&lt;th&gt;特点&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;冷启动（Cold Launch）&lt;/td&gt;
&lt;td&gt;App完全不在内存中，需要从头开始加载&lt;/td&gt;
&lt;td&gt;耗时最长，需要完整执行所有启动流程&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;热启动（Warm Launch）&lt;/td&gt;
&lt;td&gt;App在后台被挂起（Suspended），重新进入前台&lt;/td&gt;
&lt;td&gt;最快，只需恢复App状态，不需要重新创建进程&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;预热启动（Pre-warm Launch）&lt;/td&gt;
&lt;td&gt;系统预测用户可能启动App，提前在后台执行部分启动流程&lt;/td&gt;
&lt;td&gt;iOS 15+引入，介于冷启动和热启动之间&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre class="mermaid"&gt;graph LR
subgraph "冷启动（耗时最长）"
A1[创建进程] --&gt; A2[加载dylib]
A2 --&gt; A3[Rebase/Bind]
A3 --&gt; A4[+load]
A4 --&gt; A5[main]
A5 --&gt; A6[首帧渲染]
end
subgraph "预热启动（iOS 15+）"
B1[系统提前完成（后台）:&lt;br/&gt;创建进程 → 加载dylib → Rebase/Bind] --&gt; B2[用户点击后执行:&lt;br/&gt;+load → main → 首帧渲染]
end
subgraph "热启动（最快）"
C1[唤醒进程] --&gt; C2[WillEnterForeground]
C2 --&gt; C3[DidBecomeActive]
C3 --&gt; C4[恢复UI]
end
&lt;/pre&gt;
&lt;hr&gt;
&lt;h1 id="一冷启动cold-launch"&gt;一、冷启动（Cold Launch）&lt;/h1&gt;
&lt;p&gt;冷启动是最完整的启动流程，也是启动优化的主要关注点。&lt;/p&gt;
&lt;h2 id="冷启动流程概览"&gt;冷启动流程概览&lt;/h2&gt;
&lt;pre class="mermaid"&gt;flowchart TD
Start([App 冷启动流程]) --&gt; PreMain
subgraph PreMain["Pre-main 阶段"]
direction TB
A[加载可执行文件] --&gt; B[加载动态库&lt;br/&gt;（包括 Swift Runtime）]
B --&gt; C[Rebase &amp; Bind]
C --&gt; D[ObjC Runtime 初始化&lt;br/&gt;（类注册、Category 附加）]
D --&gt; D2[Swift Runtime 元数据注册&lt;br/&gt;（类型元数据、协议遵循表）]
D2 --&gt; D3[调用 +load 方法]
D3 --&gt; E[执行 Initializers&lt;br/&gt;（C++静态构造函数、__attribute__）]
end
PreMain --&gt; MainPhase
subgraph MainPhase["main 阶段"]
direction TB
F[main函数] --&gt; G[UIApplicationMain]
G --&gt; H[AppDelegate回调]
H --&gt; I[首帧渲染&lt;br/&gt;（创建Window、RootViewController、首屏UI）]
end
MainPhase --&gt; End([启动完成])
&lt;/pre&gt;
&lt;hr&gt;
&lt;h2 id="pre-main-阶段"&gt;Pre-main 阶段&lt;/h2&gt;
&lt;p&gt;Pre-main阶段是指从用户点击App图标到main函数执行之前的过程，这个阶段主要由dyld（动态链接器）负责。&lt;/p&gt;</description></item><item><title>Block底层原理</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/block%E5%BA%95%E5%B1%82%E5%8E%9F%E7%90%86/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/block%E5%BA%95%E5%B1%82%E5%8E%9F%E7%90%86/</guid><description>&lt;h2 id="基础概念"&gt;基础概念&lt;/h2&gt;
&lt;p&gt;Block 是 Apple 在 C 语言基础上扩展的语法特性（也称为 Closure / 闭包），它允许将一段代码和其执行时需要的上下文环境封装为一个可传递的对象。Block 在 Objective-C 和 C/C++ 中均可使用，是 GCD、动画 API、回调等场景的核心机制。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Block 的声明与调用
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; (&lt;span style="color:#f92672"&gt;^&lt;/span&gt;myBlock)(NSString &lt;span style="color:#f92672"&gt;*&lt;/span&gt;) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;^&lt;/span&gt;(NSString &lt;span style="color:#f92672"&gt;*&lt;/span&gt;name) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; NSLog(&lt;span style="color:#e6db74"&gt;@&amp;#34;Hello, %@&amp;#34;&lt;/span&gt;, name);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;myBlock(&lt;span style="color:#e6db74"&gt;@&amp;#34;World&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;一个核心问题是：&lt;strong&gt;Block 是函数指针还是对象？&lt;/strong&gt; 答案是——Block 本质上是一个 &lt;strong&gt;OC 对象&lt;/strong&gt;。它的底层是一个包含 &lt;code&gt;isa&lt;/code&gt; 指针的 C 结构体，满足 OC 对象的基本条件；同时它也包含一个函数指针（&lt;code&gt;FuncPtr&lt;/code&gt;），指向 Block 实际执行的代码。因此可以说，Block 是一个用对象形式包装了函数指针和捕获变量的特殊 OC 对象。&lt;/p&gt;
&lt;h2 id="底层数据结构"&gt;底层数据结构&lt;/h2&gt;
&lt;p&gt;通过 &lt;code&gt;clang -rewrite-objc&lt;/code&gt; 可以将 Block 语法转换为 C++ 代码，观察其底层结构。这个转换虽然不完全等同于最终编译产物，但准确反映了 Block 的数据布局和调用机制。&lt;/p&gt;
&lt;h3 id="编译器转换示例"&gt;编译器转换示例&lt;/h3&gt;
&lt;p&gt;对以下源码：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; a &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; (&lt;span style="color:#f92672"&gt;^&lt;/span&gt;block)(&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#f92672"&gt;^&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; NSLog(&lt;span style="color:#e6db74"&gt;@&amp;#34;%d&amp;#34;&lt;/span&gt;, a);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; block();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Clang 会将其转换为如下结构：&lt;/p&gt;</description></item><item><title>Codable底层原理</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/codable%E5%BA%95%E5%B1%82%E5%8E%9F%E7%90%86/</link><pubDate>Mon, 08 Jun 2026 23:06:52 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/codable%E5%BA%95%E5%B1%82%E5%8E%9F%E7%90%86/</guid><description>&lt;p&gt;&lt;code&gt;Codable&lt;/code&gt; 是 Swift 4 引入的序列化方案，官方定位是替代 Objective-C 时代的 &lt;code&gt;NSCoding&lt;/code&gt;、以及各种第三方字典转模型框架（MJExtension、YYModel、JSONModel 等）。与运行时反射方案不同，&lt;code&gt;Codable&lt;/code&gt; 通过&amp;quot;编译器自动合成 + 标准库协议抽象 + 具体格式实现&amp;quot;三层解耦，在编译期就把类型与序列化逻辑绑定好，兼具类型安全、性能和扩展性。&lt;/p&gt;
&lt;p&gt;本文基于以下 Swift 源码展开分析：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;协议定义：&lt;a href="https://github.com/apple/swift/blob/main/stdlib/public/core/Codable.swift"&gt;&lt;code&gt;swift/stdlib/public/core/Codable.swift&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;编译器合成：&lt;a href="https://github.com/apple/swift/blob/main/lib/Sema/DerivedConformanceCodable.cpp"&gt;&lt;code&gt;swift/lib/Sema/DerivedConformanceCodable.cpp&lt;/code&gt;&lt;/a&gt;、&lt;code&gt;DerivedConformanceCodingKey.cpp&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Foundation 实现：&lt;a href="https://github.com/apple/swift-corelibs-foundation/blob/main/Sources/Foundation/JSONEncoder.swift"&gt;&lt;code&gt;swift-corelibs-foundation/Sources/Foundation/JSONEncoder.swift&lt;/code&gt;&lt;/a&gt;、&lt;code&gt;JSONDecoder.swift&lt;/code&gt;、&lt;code&gt;PropertyListEncoder.swift&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="整体架构"&gt;整体架构&lt;/h2&gt;
&lt;p&gt;在开始深入之前，先建立整体印象。&lt;code&gt;Codable&lt;/code&gt; 可以拆成三层角色：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;用户类型层&lt;/strong&gt;：业务中的 &lt;code&gt;struct&lt;/code&gt; / &lt;code&gt;class&lt;/code&gt; / &lt;code&gt;enum&lt;/code&gt;，声明遵循 &lt;code&gt;Codable&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;标准库与编译器层&lt;/strong&gt;：标准库定义 &lt;code&gt;Encodable&lt;/code&gt; / &lt;code&gt;Decodable&lt;/code&gt; / &lt;code&gt;Encoder&lt;/code&gt; / &lt;code&gt;Decoder&lt;/code&gt; 等协议，编译器为符合条件的类型合成 &lt;code&gt;encode(to:)&lt;/code&gt; 和 &lt;code&gt;init(from:)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;格式实现层&lt;/strong&gt;：Foundation 或第三方提供具体 &lt;code&gt;Encoder&lt;/code&gt; / &lt;code&gt;Decoder&lt;/code&gt;，负责把容器操作落到 JSON、Plist、BSON 等格式上&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="mermaid"&gt;flowchart LR
subgraph L1[用户类型层]
A[struct / class / enum&lt;br/&gt;声明遵循 Codable]
end
subgraph L2[标准库与编译器层]
B[Encodable / Decodable&lt;br/&gt;协议要求]
C["编译器合成&lt;br/&gt;encode(to:) / init(from:)"]
D[Encoder / Decoder&lt;br/&gt;容器协议]
B --&gt; C
C --&gt; D
end
subgraph L3[格式实现层]
E[JSONEncoder / JSONDecoder&lt;br/&gt;PropertyListEncoder / 第三方实现]
F[Data / 字符串 / 其他格式]
E --&gt; F
end
A --&gt;|conforms to| B
D --&gt;|由具体类型实现| E
&lt;/pre&gt;
&lt;p&gt;核心思想是：&lt;strong&gt;标准库只定义&amp;quot;如何描述一个可编码类型&amp;quot;和&amp;quot;编码器需要提供什么能力&amp;quot;，具体的格式（JSON、Plist、BSON…）由 Foundation 或第三方实现&lt;/strong&gt;。用户类型只需要遵循协议，剩下的由编译器在 SIL 层自动生成。&lt;/p&gt;</description></item><item><title>KVC底层原理</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/kvc%E5%BA%95%E5%B1%82%E5%8E%9F%E7%90%86/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/kvc%E5%BA%95%E5%B1%82%E5%8E%9F%E7%90%86/</guid><description>&lt;h2 id="基础概念"&gt;基础概念&lt;/h2&gt;
&lt;p&gt;KVC（Key-Value Coding，键值编码）是 Apple 提供的一种通过字符串 key 间接访问对象属性的机制，定义在 &lt;code&gt;NSKeyValueCoding&lt;/code&gt; 协议中，&lt;code&gt;NSObject&lt;/code&gt; 默认遵循该协议。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 直接访问
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;person.name &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;@&amp;#34;Tom&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NSString &lt;span style="color:#f92672"&gt;*&lt;/span&gt;name &lt;span style="color:#f92672"&gt;=&lt;/span&gt; person.name;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// KVC 访问
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[person setValue:&lt;span style="color:#e6db74"&gt;@&amp;#34;Tom&amp;#34;&lt;/span&gt; forKey:&lt;span style="color:#e6db74"&gt;@&amp;#34;name&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NSString &lt;span style="color:#f92672"&gt;*&lt;/span&gt;name &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [person valueForKey:&lt;span style="color:#e6db74"&gt;@&amp;#34;name&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;KVC 的核心价值在于：通过字符串动态访问属性，不需要在编译期知道属性名。这使得字典转模型、序列化/反序列化、Interface Builder 的 Runtime Attributes 等场景成为可能。&lt;/p&gt;
&lt;h2 id="setvalueforkey-的底层流程"&gt;setValue:forKey: 的底层流程&lt;/h2&gt;
&lt;p&gt;当调用 &lt;code&gt;[obj setValue:value forKey:@&amp;quot;name&amp;quot;]&lt;/code&gt; 时，Runtime 按照以下顺序查找：&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart TD
A["setValue:forKey:@'name'"] --&gt; B{"查找 setter 方法"}
B --&gt;|"找到"| C["调用 setter"]
B --&gt;|"未找到"| D{"accessInstanceVariablesDirectly&lt;br/&gt;返回 YES?"}
D --&gt;|"YES"| E{"按顺序查找实例变量&lt;br/&gt;_name → _isName → name → isName"}
D --&gt;|"NO"| F["调用 setValue:forUndefinedKey:&lt;br/&gt;默认抛出 NSUndefinedKeyException"]
E --&gt;|"找到"| G["直接设置实例变量值"]
E --&gt;|"未找到"| F
&lt;/pre&gt;
&lt;h3 id="第一步查找-setter-方法"&gt;第一步：查找 setter 方法&lt;/h3&gt;
&lt;p&gt;Runtime 按以下顺序查找 setter 方法：&lt;/p&gt;</description></item><item><title>KVO底层原理</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/kvo%E5%BA%95%E5%B1%82%E5%8E%9F%E7%90%86/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/kvo%E5%BA%95%E5%B1%82%E5%8E%9F%E7%90%86/</guid><description>&lt;h2 id="基础概念"&gt;基础概念&lt;/h2&gt;
&lt;p&gt;KVO（Key-Value Observing，键值观察）是 Apple 基于 KVC 实现的一种观察者模式，允许对象监听另一个对象特定属性的变化。当被观察对象的属性值发生改变时，观察者会收到通知。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 注册观察
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[person addObserver:self
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; forKeyPath:&lt;span style="color:#e6db74"&gt;@&amp;#34;name&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; options:NSKeyValueObservingOptionNew &lt;span style="color:#f92672"&gt;|&lt;/span&gt; NSKeyValueObservingOptionOld
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; context:nil];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 接收通知
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;observeValueForKeyPath:&lt;/span&gt;(NSString &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)keyPath
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;ofObject:&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;id&lt;/span&gt;)object
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;change:&lt;/span&gt;(NSDictionary&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;NSKeyValueChangeKey, &lt;span style="color:#66d9ef"&gt;id&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)change
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;context:&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)context {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; ([keyPath isEqualToString:&lt;span style="color:#e6db74"&gt;@&amp;#34;name&amp;#34;&lt;/span&gt;]) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; NSLog(&lt;span style="color:#e6db74"&gt;@&amp;#34;name changed: %@ → %@&amp;#34;&lt;/span&gt;, change[NSKeyValueChangeOldKey], change[NSKeyValueChangeNewKey]);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 移除观察
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;dealloc&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [person removeObserver:self forKeyPath:&lt;span style="color:#e6db74"&gt;@&amp;#34;name&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="kvo-的底层实现原理isa-swizzling"&gt;KVO 的底层实现原理：isa-swizzling&lt;/h2&gt;
&lt;p&gt;KVO 的核心实现机制是 &lt;strong&gt;isa-swizzling&lt;/strong&gt;（isa 指针替换）。当对象被添加观察者时，Runtime 会在运行时动态创建该对象所属类的一个子类，并将对象的 isa 指针指向这个新的子类。&lt;/p&gt;
&lt;h3 id="完整流程"&gt;完整流程&lt;/h3&gt;
&lt;pre class="mermaid"&gt;flowchart TD
A["addObserver:forKeyPath:"] --&gt; B["Runtime 动态创建子类&lt;br/&gt;NSKVONotifying_ClassName"]
B --&gt; C["重写被观察属性的 setter 方法"]
B --&gt; D["重写 class 方法&lt;br/&gt;返回原始类"]
B --&gt; E["重写 dealloc 方法"]
B --&gt; F["重写 _isKVOA 方法&lt;br/&gt;返回 YES"]
C --&gt; G["将对象的 isa 指向&lt;br/&gt;NSKVONotifying_ClassName"]
G --&gt; H["当属性值改变时"]
H --&gt; I["调用 willChangeValueForKey:"]
I --&gt; J["调用原始 setter 方法"]
J --&gt; K["调用 didChangeValueForKey:"]
K --&gt; L["通知所有观察者"]
&lt;/pre&gt;
&lt;h3 id="第一步动态创建子类"&gt;第一步：动态创建子类&lt;/h3&gt;
&lt;p&gt;当首次对某个类的实例调用 &lt;code&gt;addObserver:forKeyPath:options:context:&lt;/code&gt; 时，Runtime 会：&lt;/p&gt;</description></item><item><title>Mach-O的链接、装载与库</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/mach-o%E7%9A%84%E9%93%BE%E6%8E%A5-%E8%A3%85%E8%BD%BD%E4%B8%8E%E5%BA%93/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/mach-o%E7%9A%84%E9%93%BE%E6%8E%A5-%E8%A3%85%E8%BD%BD%E4%B8%8E%E5%BA%93/</guid><description>&lt;p&gt;本文深入介绍iOS/macOS开发中的Mach-O文件格式、动态库与静态库，帮助理解程序的链接、装载过程，以及Rebase/Bind的底层原理。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="一基础概念"&gt;一、基础概念&lt;/h2&gt;
&lt;p&gt;在深入学习之前，先了解几个核心概念。&lt;/p&gt;
&lt;h3 id="10-从源代码到可执行文件"&gt;1.0 从源代码到可执行文件&lt;/h3&gt;
&lt;p&gt;一段源代码要变成可执行文件，需要经历以下几个阶段：&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart TB
A["源代码 (.m/.swift)"] --&gt; B["预处理&lt;br/&gt;展开宏、处理#import/#include"]
B --&gt; C["编译&lt;br/&gt;源代码 → 汇编代码"]
C --&gt; D["汇编&lt;br/&gt;汇编代码 → 目标文件(.o)"]
D --&gt; E["链接&lt;br/&gt;目标文件 + 库 → 可执行文件"]
E --&gt; F["可执行文件"]
&lt;/pre&gt;
&lt;h3 id="11-什么是符号symbol"&gt;1.1 什么是符号（Symbol）&lt;/h3&gt;
&lt;p&gt;符号是程序中函数、变量、类等实体的&lt;strong&gt;名称标识&lt;/strong&gt;。当你写下一个函数调用时，编译器需要知道这个函数在哪里，符号就是用来定位它的。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 这段代码中包含多个符号
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;myFunction&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;) { &lt;span style="color:#75715e"&gt;// 定义了符号 _myFunction
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; NSLog(&lt;span style="color:#e6db74"&gt;@&amp;#34;Hello&amp;#34;&lt;/span&gt;); &lt;span style="color:#75715e"&gt;// 引用了外部符号 _NSLog
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; globalVar &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;; &lt;span style="color:#75715e"&gt;// 定义了符号 _globalVar
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;符号分为两类：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;已定义符号&lt;/strong&gt;：在当前编译单元（即当前源文件编译生成的.o文件）中有具体代码或数据定义的符号（如上例中的 &lt;code&gt;_myFunction&lt;/code&gt; 和 &lt;code&gt;_globalVar&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;未定义符号&lt;/strong&gt;：当前编译单元只是引用，实际定义在其他编译单元或库中的符号（如上例中的 &lt;code&gt;_NSLog&lt;/code&gt;），需要在链接时解析&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="12-什么是链接linking"&gt;1.2 什么是链接（Linking）&lt;/h3&gt;
&lt;p&gt;链接是将多个编译后的目标文件（.o）组合成一个可执行文件的过程。链接器的核心工作是&lt;strong&gt;符号解析&lt;/strong&gt;——把所有&amp;quot;未定义符号&amp;quot;与其他编译单元中的&amp;quot;已定义符号&amp;quot;关联起来。&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart LR
subgraph 输入
A["main.o&lt;br/&gt;已定义: _main&lt;br/&gt;未定义: _foo"]
B["foo.o&lt;br/&gt;已定义: _foo&lt;br/&gt;未定义: _NSLog"]
C["Foundation&lt;br/&gt;已定义: _NSLog"]
end
A --&gt; D["链接器&lt;br/&gt;符号解析"]
B --&gt; D
C --&gt; D
D --&gt; E["可执行文件&lt;br/&gt;所有符号已解析"]
&lt;/pre&gt;
&lt;h4 id="符号解析的过程"&gt;符号解析的过程&lt;/h4&gt;
&lt;p&gt;链接器会遍历所有输入的目标文件和库，执行以下步骤：&lt;/p&gt;</description></item><item><title>Objective-C与Swift区别</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/objective-c%E4%B8%8Eswift%E5%8C%BA%E5%88%AB/</link><pubDate>Fri, 08 May 2026 13:07:14 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/objective-c%E4%B8%8Eswift%E5%8C%BA%E5%88%AB/</guid><description>&lt;h2 id="语言设计"&gt;语言设计&lt;/h2&gt;
&lt;h3 id="objective-c"&gt;Objective-C&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;是C的超集，在C的基础上添加了Smalltalk风格的消息传递机制&lt;/li&gt;
&lt;li&gt;对象间交互不通过调用方法而是发送消息，以实现面向对象编程和超高的动态性&lt;/li&gt;
&lt;li&gt;动态性由 Objective-C Runtime 系统支持，可以在运行时修改类结构、方法交换等，详见 &lt;a href="https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/runtime/"&gt;Runtime&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;弱类型语言，核心类型&lt;code&gt;id&lt;/code&gt;可以指向任何Objective-C对象&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="swift"&gt;Swift&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;从很多现代化语言中汲取精华，是一门偏重于安全、性能的现代化语言&lt;/li&gt;
&lt;li&gt;Swift 也有自己的运行时系统（Swift Runtime），但设计哲学完全不同，更强调编译期优化&lt;/li&gt;
&lt;li&gt;强类型语言，编译器在编译阶段进行严格的类型检查&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="语法特性"&gt;语法特性&lt;/h2&gt;
&lt;h3 id="objective-c-1"&gt;Objective-C&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;语法冗长，需要显式声明类型&lt;/li&gt;
&lt;li&gt;命名通常较长且需要添加前缀避免冲突&lt;/li&gt;
&lt;li&gt;需要单独的&lt;code&gt;.h&lt;/code&gt;和&lt;code&gt;.m&lt;/code&gt;文件声明接口和实现&lt;/li&gt;
&lt;li&gt;引用其他文件/模块必须要&lt;code&gt;import&lt;/code&gt;（&lt;a href="https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/objective-c%E4%B8%ADimport%E8%AF%A6%E8%A7%A3/"&gt;Objective-C中import详解&lt;/a&gt;）&lt;/li&gt;
&lt;li&gt;协议不支持默认实现&lt;/li&gt;
&lt;li&gt;泛型是&amp;quot;轻量级泛型&amp;quot;，仅用于编译时类型检查，运行时类型信息会被擦除&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="swift-1"&gt;Swift&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;语法简洁，强大的类型推断减少冗余的类型声明&lt;/li&gt;
&lt;li&gt;有命名空间（模块）的存在避免命名冲突&lt;/li&gt;
&lt;li&gt;不需要单独的头文件声明接口&lt;/li&gt;
&lt;li&gt;默认情况下变量必须初始化&lt;/li&gt;
&lt;li&gt;引用同模块的其他文件不需要&lt;code&gt;import&lt;/code&gt;（&lt;a href="https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/swift%E4%B8%ADimport%E8%AF%A6%E8%A7%A3/"&gt;Swift中import详解&lt;/a&gt;）&lt;/li&gt;
&lt;li&gt;协议支持默认实现、支持拓展，支持关联类型以实现泛型协议&lt;/li&gt;
&lt;li&gt;值类型也可以遵守协议&lt;/li&gt;
&lt;li&gt;泛型在编译时进行类型特化优化，支持完整的泛型元编程&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="内存管理"&gt;内存管理&lt;/h2&gt;
&lt;h3 id="objective-c-2"&gt;Objective-C&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;大部分都是引用类型，依赖引用计数管理内存&lt;/li&gt;
&lt;li&gt;ARC在编译时自动插入&lt;code&gt;retain&lt;/code&gt;、&lt;code&gt;release&lt;/code&gt;、&lt;code&gt;autorelease&lt;/code&gt;调用&lt;/li&gt;
&lt;li&gt;64位系统使用优化的isa（Non-pointer isa），通过位域在isa中嵌入引用计数（&lt;code&gt;extra_rc&lt;/code&gt;字段），溢出时使用SideTable存储&lt;/li&gt;
&lt;li&gt;实例变量（ivar）会被Runtime自动初始化为0/nil&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="swift-2"&gt;Swift&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;引用类型也是依赖引用计数管理内存&lt;/li&gt;
&lt;li&gt;存在大量的值类型，例如结构体、枚举、数组、字典等&lt;/li&gt;
&lt;li&gt;非逃逸的值类型的内存存在栈区由系统进行自动管理&lt;/li&gt;
&lt;li&gt;纯Swift类的引用计数直接存储在对象头部的RefCount字段中，无需SideTable，访问更高效&lt;/li&gt;
&lt;li&gt;编译器在编译时就确保了初始化，不需要运行时统一清零&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;拓展：&lt;a href="https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/%E5%80%BC%E7%B1%BB%E5%9E%8B%E5%92%8C%E5%BC%95%E7%94%A8%E7%B1%BB%E5%9E%8B%E7%9A%84%E5%8C%BA%E5%88%AB/"&gt;值类型和引用类型的区别&lt;/a&gt;
拓展：&lt;a href="https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/ios%E4%B8%AD%E7%9A%84%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86/"&gt;iOS中的内存管理&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="性能对比"&gt;性能对比&lt;/h2&gt;
&lt;h3 id="objective-c-3"&gt;Objective-C&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;基于消息传递机制本质上是动态派发，运行时查找方法实现，有一定开销&lt;/li&gt;
&lt;li&gt;ARC管理引用计数也有开销&lt;/li&gt;
&lt;li&gt;引用类型内存存在堆区，内存管理的性能开销会比栈区多很多&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="swift-3"&gt;Swift&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;方法派发尽可能使用静态派发（如对&lt;code&gt;final&lt;/code&gt;类/方法、私有方法、值类型方法的调用）&lt;/li&gt;
&lt;li&gt;编译器可以内联优化，速度接近C
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;内联优化&lt;/strong&gt;：比如A方法调用B方法，B方法调用C方法，代码编写调用A方法时编译器通过内联直接调用C方法的实现&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;值类型内存分配在栈区，性能开销相对较小&lt;/li&gt;
&lt;li&gt;虽然值类型是深拷贝，Swift为了优化值类型性能引入写时拷贝（Copy-on-Write）机制，值类型只在写操作发生深拷贝，其他时候都是浅拷贝&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="安全性"&gt;安全性&lt;/h2&gt;
&lt;h3 id="objective-c-4"&gt;Objective-C&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;弱类型（动态类型）占主导&lt;/li&gt;
&lt;li&gt;核心类型&lt;code&gt;id&lt;/code&gt;可以指向任何Objective-C对象&lt;/li&gt;
&lt;li&gt;编译器几乎不做类型检查，会有运行时崩溃的风险（如向不响应某消息的对象发送该消息）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;nil&lt;/code&gt;消息发送不会崩溃但可能导致逻辑错误，不容易感知&lt;/li&gt;
&lt;li&gt;局部变量不会自动初始化，可能包含栈上的垃圾数据（未定义行为）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="swift-4"&gt;Swift&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;可选类型强制处理空值，编译器强制解包检查&lt;/li&gt;
&lt;li&gt;强类型和编译时检查阻止了大量常见错误&lt;/li&gt;
&lt;li&gt;变量必须初始化后才能使用，编译器在编译阶段强制检查，消除未定义行为&lt;/li&gt;
&lt;li&gt;强制初始化使编译器能更精确地追踪变量生命周期，带来更多优化机会&lt;/li&gt;
&lt;li&gt;数组越界等操作会在运行时触发明确的崩溃，便于定位问题&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="编程范式"&gt;编程范式&lt;/h2&gt;
&lt;h3 id="objective-c-5"&gt;Objective-C&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;主要是面向对象编程（OOP）&lt;/li&gt;
&lt;li&gt;通过继承实现代码复用&lt;/li&gt;
&lt;li&gt;依赖Runtime实现面向切面编程（AOP），如Method Swizzling&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="swift-5"&gt;Swift&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;拥抱多范式，对函数式编程、面向协议编程（POP）、声明式编程很友好&lt;/li&gt;
&lt;li&gt;通过协议扩展提供默认实现，协议组合替代多继承&lt;/li&gt;
&lt;li&gt;值类型（struct/enum）也可以遵循协议，不再局限于类&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;拓展：&lt;a href="https://amatsuzero.github.io/LastStand/posts/interview/ios-advanced/oop-pop-aop/"&gt;OOP、POP与AOP&lt;/a&gt;&lt;/p&gt;</description></item><item><title>iOS中import详解</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/objective-c%E4%B8%ADimport%E8%AF%A6%E8%A7%A3/</link><pubDate>Mon, 08 Jun 2026 23:06:52 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/objective-c%E4%B8%ADimport%E8%AF%A6%E8%A7%A3/</guid><description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;源码版本说明&lt;/strong&gt;：本文涉及的源码基于 &lt;strong&gt;LLVM/Clang 23.0.0&lt;/strong&gt; 开发版本（llvm-project main分支，commit: &lt;code&gt;301c0d91b558&lt;/code&gt;，2026-01-16）。不同版本的实现细节可能略有差异，但核心机制保持一致。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;在Objective-C开发中，头文件引用是日常开发中最基础的操作之一。本文将从Clang编译器的角度，深入讲解iOS中各种import方式的区别、底层查找原理以及最佳实践。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;引用方式&lt;/th&gt;
&lt;th&gt;语法示例&lt;/th&gt;
&lt;th&gt;适用场景&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;#include&lt;/td&gt;
&lt;td&gt;&lt;code&gt;#include &amp;quot;Header.h&amp;quot;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;C/C++传统方式&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;#import&lt;/td&gt;
&lt;td&gt;&lt;code&gt;#import &amp;quot;Header.h&amp;quot;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Objective-C项目内部引用&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;#import&lt;/td&gt;
&lt;td&gt;&lt;code&gt;#import &amp;lt;Framework/Header.h&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;系统/第三方Framework&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;@import&lt;/td&gt;
&lt;td&gt;&lt;code&gt;@import Foundation;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Clang Modules方式&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PCH&lt;/td&gt;
&lt;td&gt;Prefix Header文件&lt;/td&gt;
&lt;td&gt;预编译公共头文件&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="include-vs-import"&gt;#include vs #import&lt;/h2&gt;
&lt;h3 id="include的工作原理"&gt;#include的工作原理&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;#include&lt;/code&gt;是C/C++中的头文件引用方式，它的工作原理非常简单：&lt;strong&gt;预处理器会将目标头文件的内容原封不动地复制粘贴到当前文件中&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;这种方式存在一个问题：&lt;strong&gt;重复引用&lt;/strong&gt;。如果多个文件都include了同一个头文件，或者存在循环引用，会导致编译错误。传统的解决方案是使用&lt;strong&gt;Include Guard&lt;/strong&gt;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Header.h
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#ifndef HEADER_H
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#define HEADER_H
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 头文件内容
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#endif
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;现代编译器还支持&lt;code&gt;#pragma once&lt;/code&gt;指令，功能相同但更简洁：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Header.h
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#pragma once
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 头文件内容
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="import的增强"&gt;#import的增强&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;#import&lt;/code&gt;是Objective-C对&lt;code&gt;#include&lt;/code&gt;的封装和增强。它在&lt;code&gt;#include&lt;/code&gt;的基础上增加了一层&lt;strong&gt;判重逻辑&lt;/strong&gt;，自动防止同一个头文件被重复引用。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objective-c" data-lang="objective-c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// BClass.m
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#import &amp;#34;AClass.h&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#import &amp;#34;AClass.h&amp;#34; &lt;/span&gt;&lt;span style="color:#75715e"&gt;// 第二次import会被自动忽略
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="双引号-vs-尖括号"&gt;双引号 vs 尖括号&lt;/h3&gt;
&lt;p&gt;在日常开发中，我们经常会看到两种不同的引用方式：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objective-c" data-lang="objective-c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#import &amp;#34;MyClass.h&amp;#34; &lt;/span&gt;&lt;span style="color:#75715e"&gt;// 双引号形式
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#import &amp;lt;UIKit/UIKit.h&amp;gt; &lt;/span&gt;&lt;span style="color:#75715e"&gt;// 尖括号形式
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;它们的核心区别在于&lt;strong&gt;搜索路径的范围不同&lt;/strong&gt;：&lt;/p&gt;</description></item><item><title>Objective-C底层原理 - NSObject</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/objective-c%E5%BA%95%E5%B1%82%E5%8E%9F%E7%90%86-nsobject/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/objective-c%E5%BA%95%E5%B1%82%E5%8E%9F%E7%90%86-nsobject/</guid><description>&lt;p&gt;本文将深入探讨&lt;code&gt;Objective-C&lt;/code&gt;中所有对象的基类&lt;code&gt;NSObject&lt;/code&gt;的底层实现原理，涵盖对象本质、isa指针机制、Tagged Pointer、引用计数、内存布局等核心概念。&lt;/p&gt;
&lt;h2 id="nsobject-的本质c-结构体"&gt;NSObject 的本质：C 结构体&lt;/h2&gt;
&lt;p&gt;在&lt;code&gt;Objective-C&lt;/code&gt;的底层实现中，&lt;code&gt;NSObject&lt;/code&gt;的本质是一个&lt;code&gt;C&lt;/code&gt;结构体。在苹果运行时源码中可以看到：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 底层运行时定义
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; objc_object {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Class isa; &lt;span style="color:#75715e"&gt;// 指向对象所属类的指针
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 类型别名定义
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;typedef&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; objc_object NSObject;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这意味着，当我们通过&lt;code&gt;NSObject *obj = [[NSObject alloc] init];&lt;/code&gt;创建一个 NSObject 实例时，实际上在堆上分配了一个&lt;code&gt;struct objc_object&lt;/code&gt;结构体，而变量&lt;code&gt;obj&lt;/code&gt;只是一个指向该结构体的指针。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 这行代码在底层实际上做了类似下面的事情：
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NSObject &lt;span style="color:#f92672"&gt;*&lt;/span&gt;obj &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [[NSObject alloc] init];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 等效的伪C代码:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 1. 调用 alloc 类方法，其核心是调用 malloc 在堆上分配一块足够大的内存
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 大小至少是 sizeof(struct objc_object)，即一个isa指针的大小
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NSObject &lt;span style="color:#f92672"&gt;*&lt;/span&gt;obj &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (NSObject &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)malloc(&lt;span style="color:#66d9ef"&gt;sizeof&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; objc_object));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 2. 初始化这块内存，最重要的是设置 isa 指针，让它指向 NSObject 这个类
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;obj&lt;span style="color:#f92672"&gt;-&amp;gt;&lt;/span&gt;isa &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [NSObject &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt;]; &lt;span style="color:#75715e"&gt;// 实际过程更复杂，但本质如此
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 3. 其他初始化工作 (init)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;那么这里提到的&lt;code&gt;isa&lt;/code&gt;指针是什么呢？&lt;/p&gt;</description></item><item><title>SIL（Swift Intermediate Language）</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/sil/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/sil/</guid><description>&lt;p&gt;SIL（Swift Intermediate Language，Swift 中间语言）是 Swift 编译器在编译过程中生成的一种&lt;strong&gt;中间表示&lt;/strong&gt;（Intermediate Representation，IR）。它位于 Swift 源码与 LLVM IR 之间，是 Swift 编译器架构中至关重要的一层。&lt;/p&gt;
&lt;p&gt;SIL 的设计目标是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;对 Swift 语言的&lt;strong&gt;高级语义&lt;/strong&gt;进行精确建模&lt;/li&gt;
&lt;li&gt;在&lt;strong&gt;高层抽象&lt;/strong&gt;的基础上执行强大的优化&lt;/li&gt;
&lt;li&gt;保留足够的类型信息，用于&lt;strong&gt;诊断&lt;/strong&gt;和&lt;strong&gt;安全检查&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;作为 Swift 特有优化的载体，弥补 LLVM IR 无法直接表达 Swift 语义的不足&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;SIL 并不是给开发者日常编写的语言，而是编译器的内部表示。理解它有助于深入理解 Swift 的编译过程、性能优化原理和内存管理机制。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="swift-编译流程概览"&gt;Swift 编译流程概览&lt;/h2&gt;
&lt;p&gt;在了解 SIL 之前，需要先理解 Swift 的整体编译流程：&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart TD
A[Swift 源代码 .swift] --&gt; B[词法分析 Lexer]
B --&gt; C[语法分析 Parser]
C --&gt; D[语义分析 Sema]
D --&gt; E[SILGen: 生成 Raw SIL]
E --&gt; F[SIL 优化 Guaranteed Passes]
F --&gt; G[SIL 优化 General Passes]
G --&gt; H[IRGen: 生成 LLVM IR]
H --&gt; I[LLVM 优化]
I --&gt; J[机器码 .o]
J --&gt; K[链接器 Linker]
K --&gt; L[可执行文件 / 动态库]
&lt;/pre&gt;
&lt;h3 id="各阶段简述"&gt;各阶段简述&lt;/h3&gt;
&lt;h4 id="词法分析lexer"&gt;词法分析（Lexer）&lt;/h4&gt;
&lt;p&gt;编译的第一步。Lexer 逐字符扫描 &lt;code&gt;.swift&lt;/code&gt; 源文件，将其切分为一系列&lt;strong&gt;Token（词法单元）&lt;/strong&gt;，例如关键字 &lt;code&gt;func&lt;/code&gt;、标识符 &lt;code&gt;add&lt;/code&gt;、运算符 &lt;code&gt;+&lt;/code&gt;、字面量 &lt;code&gt;42&lt;/code&gt;、左右括号等。Token 是后续所有分析的最小输入单位。这一步会剥离注释和空白，但保留它们的位置信息以便后续生成精确的诊断信息（错误提示的行号和列号）。&lt;/p&gt;</description></item><item><title>Swift中import详解</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/swift%E4%B8%ADimport%E8%AF%A6%E8%A7%A3/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/swift%E4%B8%ADimport%E8%AF%A6%E8%A7%A3/</guid><description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;源码版本说明&lt;/strong&gt;：本文涉及的源码基于 &lt;strong&gt;Swift 编译器&lt;/strong&gt; 开发版本（swift main分支，commit: &lt;code&gt;e0db5152d4d4&lt;/code&gt;，2026-01-19）。不同版本的实现细节可能略有差异，但核心机制保持一致。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;在前一篇文章&lt;a href="https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/objective-c%E4%B8%ADimport%E8%AF%A6%E8%A7%A3/"&gt;Objective-C中import详解&lt;/a&gt;中，我们深入探讨了 Objective-C 中的 import 机制，包括 &lt;code&gt;#include&lt;/code&gt;、&lt;code&gt;#import&lt;/code&gt;、&lt;code&gt;@import&lt;/code&gt; 以及 Clang Modules 的工作原理。本文将继续从 Swift 编译器的角度，讲解 Swift 中 import 的语法、模块查找机制、底层实现原理以及与 Objective-C 的互操作。&lt;/p&gt;
&lt;h2 id="从-clang-module-到-swift-module"&gt;从 Clang Module 到 Swift Module&lt;/h2&gt;
&lt;p&gt;在深入 Swift 的 import 机制之前，让我们先回顾一下上一篇文章中 Clang Module 的核心概念。&lt;/p&gt;
&lt;h3 id="clang-module-核心概念回顾"&gt;Clang Module 核心概念回顾&lt;/h3&gt;
&lt;p&gt;在 Objective-C 文章中，我们学习了 Clang Module 的几个关键特性：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;module.modulemap&lt;/strong&gt;：定义模块结构的配置文件&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;framework module Foundation {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; umbrella header &lt;span style="color:#e6db74"&gt;&amp;#34;Foundation.h&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;export&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;预编译模块缓存（.pcm 文件）&lt;/strong&gt;：Clang 将模块编译为二进制格式，缓存以加速后续编译&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;懒加载机制&lt;/strong&gt;：只加载实际使用的声明，未使用的部分不会被解析&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;自动链接&lt;/strong&gt;：&lt;code&gt;@import&lt;/code&gt; 会自动链接对应的库，无需手动配置&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;模块查找路径&lt;/strong&gt;：通过 &lt;code&gt;-I&lt;/code&gt;、&lt;code&gt;-F&lt;/code&gt; 等参数指定搜索路径&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="swift-如何继承-clang-module-的设计"&gt;Swift 如何继承 Clang Module 的设计&lt;/h3&gt;
&lt;p&gt;Swift 的模块系统并非从零开始设计，而是&lt;strong&gt;站在 Clang Module 的肩膀上&lt;/strong&gt;，继承了其核心优势，并针对 Swift 的特性进行了扩展：&lt;/p&gt;</description></item><item><title>Swift二进制兼容性</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/swift%E4%BA%8C%E8%BF%9B%E5%88%B6%E5%85%BC%E5%AE%B9%E6%80%A7/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/swift%E4%BA%8C%E8%BF%9B%E5%88%B6%E5%85%BC%E5%AE%B9%E6%80%A7/</guid><description>&lt;p&gt;Swift二进制兼容性是指Swift编译后的二进制代码能够跨版本、跨模块正确链接和运行的能力。它由三个核心机制组成：&lt;strong&gt;ABI稳定&lt;/strong&gt;（Swift 5.0）、&lt;strong&gt;模块稳定性&lt;/strong&gt;（Swift 5.1）和&lt;strong&gt;Library Evolution&lt;/strong&gt;。这三者共同使得Swift二进制框架的分发成为可能。&lt;/p&gt;
&lt;pre class="mermaid"&gt;graph TD
A[Swift二进制兼容性] --&gt; B[ABI稳定&lt;br/&gt;Swift 5.0]
A --&gt; C[模块稳定性&lt;br/&gt;Swift 5.1]
A --&gt; D[Library Evolution]
B --&gt; B1[统一运行时&lt;br/&gt;固定调用约定/内存布局]
C --&gt; C1[.swiftinterface&lt;br/&gt;跨编译器版本导入模块]
D --&gt; D1[运行时布局查询&lt;br/&gt;库可独立于客户端更新]
B1 --&gt; E[二进制框架分发]
C1 --&gt; E
D1 --&gt; E
&lt;/pre&gt;
&lt;h2 id="abi稳定"&gt;ABI稳定&lt;/h2&gt;
&lt;h3 id="什么是abi"&gt;什么是ABI&lt;/h3&gt;
&lt;p&gt;ABI（Application Binary Interface，应用程序二进制接口）定义了二进制层面的接口规范，包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;数据类型的大小和对齐方式&lt;/strong&gt;：如Int在64位系统上是8字节&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;函数调用约定&lt;/strong&gt;：参数如何传递、返回值如何获取&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;名称修饰（Name Mangling）规则&lt;/strong&gt;：函数和类型在二进制中的命名方式&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;内存布局&lt;/strong&gt;：对象在内存中的结构&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;异常处理机制&lt;/strong&gt;：错误如何在二进制层面传播&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;运行时元数据格式&lt;/strong&gt;：类型信息的存储方式&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="abi-vs-api"&gt;ABI vs API&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;特性&lt;/th&gt;
&lt;th&gt;API（源码接口）&lt;/th&gt;
&lt;th&gt;ABI（二进制接口）&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;层面&lt;/td&gt;
&lt;td&gt;源代码层面&lt;/td&gt;
&lt;td&gt;编译后的二进制层面&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;兼容性检查&lt;/td&gt;
&lt;td&gt;编译时&lt;/td&gt;
&lt;td&gt;链接时/运行时&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;关注点&lt;/td&gt;
&lt;td&gt;函数签名、类型定义&lt;/td&gt;
&lt;td&gt;内存布局、调用约定&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;变化影响&lt;/td&gt;
&lt;td&gt;需要重新编译&lt;/td&gt;
&lt;td&gt;需要重新链接或替换二进制&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;一个简单的例子：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// API层面：函数签名&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;calculate&lt;/span&gt;(value: Int) -&amp;gt; Int
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// ABI层面关注的是：&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// - Int在内存中占多少字节&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// - value参数通过哪个寄存器传递&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// - 返回值通过哪个寄存器返回&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// - 函数在二进制中的符号名是什么&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="abi不稳定时期的问题"&gt;ABI不稳定时期的问题&lt;/h3&gt;
&lt;p&gt;在Swift 5.0之前，Swift的ABI是不稳定的。这意味着：&lt;/p&gt;</description></item><item><title>Swift 宏</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/swift%E5%AE%8F/</link><pubDate>Mon, 04 May 2026 00:38:29 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/swift%E5%AE%8F/</guid><description>&lt;p&gt;Swift 5.9（WWDC 2023）引入的&lt;strong&gt;宏（Macro）&lt;strong&gt;是近几年语言层最大的一次能力扩展。它让 Swift 第一次具备了&lt;/strong&gt;编译期代码生成&lt;/strong&gt;的官方机制——你可以在源码层面写一段&amp;quot;能生成代码的代码&amp;quot;，编译器会在类型检查前把它展开成真正的 Swift 源码，再走正常的编译流程。SwiftUI 的 &lt;code&gt;#Preview&lt;/code&gt;、Observation 框架的 &lt;code&gt;@Observable&lt;/code&gt;、SwiftData 的 &lt;code&gt;@Model&lt;/code&gt;、Swift Testing 的 &lt;code&gt;@Test&lt;/code&gt; / &lt;code&gt;#expect&lt;/code&gt;、FoundationModels 的 &lt;code&gt;@Generable&lt;/code&gt; / &lt;code&gt;@Tool&lt;/code&gt;，全都是宏。&lt;/p&gt;
&lt;h2 id="一为什么要有宏"&gt;一、为什么要有宏&lt;/h2&gt;
&lt;h3 id="11-swift-之前能做什么又差在哪"&gt;1.1 Swift 之前能做什么，又差在哪&lt;/h3&gt;
&lt;p&gt;在宏之前，Swift 已经有一整套&amp;quot;元编程&amp;quot;手段，但每一种都有明显的边界：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;机制&lt;/th&gt;
&lt;th&gt;做什么&lt;/th&gt;
&lt;th&gt;局限&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;@propertyWrapper&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;给属性注入行为（如 &lt;code&gt;@Published&lt;/code&gt;、&lt;code&gt;@State&lt;/code&gt;）&lt;/td&gt;
&lt;td&gt;只能包属性，不能生成方法、不能生成类型、不能访问其他成员&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;@resultBuilder&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;把一段 DSL 收集成表达式（如 SwiftUI 的 &lt;code&gt;ViewBuilder&lt;/code&gt;）&lt;/td&gt;
&lt;td&gt;只作用于闭包里，无法改类型定义&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;KeyPath + Mirror&lt;/td&gt;
&lt;td&gt;运行时反射读写属性&lt;/td&gt;
&lt;td&gt;只能读，类型安全差，性能差（见 &lt;a href="https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/ios%E5%8F%8D%E5%B0%84/"&gt;iOS反射&lt;/a&gt;）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Codable 等编译器魔法&lt;/td&gt;
&lt;td&gt;自动合成 &lt;code&gt;init(from:)&lt;/code&gt; / &lt;code&gt;encode(to:)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;只有编译器内部能写，开发者写不出同等能力的东西&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sourcery / SwiftGen&lt;/td&gt;
&lt;td&gt;文本级代码生成&lt;/td&gt;
&lt;td&gt;游离于编译器之外，无类型信息、无法访问 AST&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Objective-C &lt;code&gt;#define&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;纯文本替换&lt;/td&gt;
&lt;td&gt;没有作用域、没有类型、没有卫生（hygiene），对调试器和 IDE 极不友好&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;宏&lt;/strong&gt;就是要一次性补齐这块能力：在保留类型安全与 IDE 体验的前提下，把&amp;quot;只有 Swift 编译器团队能写的代码生成&amp;quot;开放给所有开发者。&lt;/p&gt;</description></item><item><title>Swift底层原理-结构体、类和协议</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/swift%E5%BA%95%E5%B1%82%E5%8E%9F%E7%90%86-%E7%BB%93%E6%9E%84%E4%BD%93-%E7%B1%BB%E5%92%8C%E5%8D%8F%E8%AE%AE/</link><pubDate>Wed, 06 May 2026 22:05:01 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/swift%E5%BA%95%E5%B1%82%E5%8E%9F%E7%90%86-%E7%BB%93%E6%9E%84%E4%BD%93-%E7%B1%BB%E5%92%8C%E5%8D%8F%E8%AE%AE/</guid><description>&lt;p&gt;在&lt;a href="https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/objective-c%E5%BA%95%E5%B1%82%E5%8E%9F%E7%90%86-nsobject/"&gt;Objective-C底层原理-NSObject&lt;/a&gt;文章中，我们深入了解了Objective-C对象的底层实现。本文将探讨Swift中类和结构体的底层原理。&lt;/p&gt;
&lt;h2 id="swift数据结构的分类"&gt;Swift数据结构的分类&lt;/h2&gt;
&lt;p&gt;Swift中的类根据是否继承自NSObject，在底层实现上存在显著差异：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;继承自NSObject的Swift类&lt;/strong&gt;：兼容Objective-C运行时，支持完整的Objective-C特性&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;纯Swift类&lt;/strong&gt;：使用Swift原生运行时，性能更优但Objective-C互操作性受限&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Swift中结构体是值类型，具有以下核心特征：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;栈上分配内存（&lt;a href="https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/%E5%80%BC%E7%B1%BB%E5%9E%8B%E5%92%8C%E5%BC%95%E7%94%A8%E7%B1%BB%E5%9E%8B%E7%9A%84%E5%8C%BA%E5%88%AB/#%E5%80%BC%E7%B1%BB%E5%9E%8B%E7%9A%84%E9%80%83%E9%80%B8"&gt;非逃逸&lt;/a&gt;情况）&lt;/li&gt;
&lt;li&gt;值语义和完整拷贝&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/%E5%80%BC%E7%B1%BB%E5%9E%8B%E5%92%8C%E5%BC%95%E7%94%A8%E7%B1%BB%E5%9E%8B%E7%9A%84%E5%8C%BA%E5%88%AB/#%E5%86%99%E6%97%B6%E6%8B%B7%E8%B4%9Dcopy-on-write"&gt;写时拷贝&lt;/a&gt;优化（COW）&lt;/li&gt;
&lt;li&gt;静态方法派发&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="swift类的底层实现"&gt;Swift类的底层实现&lt;/h2&gt;
&lt;h3 id="继承自nsobject的swift类"&gt;继承自NSObject的Swift类&lt;/h3&gt;
&lt;p&gt;当Swift类继承自NSObject时，必须兼容Objective-C的运行时系统，其底层实现与Objective-C对象高度一致。&lt;/p&gt;
&lt;h4 id="内存布局"&gt;内存布局&lt;/h4&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Class&lt;/span&gt;: NSObject {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; name: String
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; isMale: Bool
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; age: Int
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;init&lt;/span&gt;(name: String, isMale: Bool, age: Int) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;.name = name
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;.isMale = isMale
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;.age = age
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;super&lt;/span&gt;.&lt;span style="color:#66d9ef"&gt;init&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;实例内存布局：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;偏移量&lt;/th&gt;
&lt;th&gt;内容&lt;/th&gt;
&lt;th&gt;大小&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0x0-0x7&lt;/td&gt;
&lt;td&gt;isa_t isa&lt;/td&gt;
&lt;td&gt;8字节&lt;/td&gt;
&lt;td&gt;指向类对象，包含优化的位域信息&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0x8-0x17&lt;/td&gt;
&lt;td&gt;String name&lt;/td&gt;
&lt;td&gt;16字节&lt;/td&gt;
&lt;td&gt;Swift String结构（64位系统）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0x18&lt;/td&gt;
&lt;td&gt;Bool isMale&lt;/td&gt;
&lt;td&gt;1字节&lt;/td&gt;
&lt;td&gt;布尔值&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0x19-0x1F&lt;/td&gt;
&lt;td&gt;(padding)&lt;/td&gt;
&lt;td&gt;7字节&lt;/td&gt;
&lt;td&gt;Swift编译器根据下一个字段（Int，8字节对齐要求）自动插入填充，确保Int字段从8的倍数地址开始&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0x20-0x27&lt;/td&gt;
&lt;td&gt;Int age&lt;/td&gt;
&lt;td&gt;8字节&lt;/td&gt;
&lt;td&gt;64位整数&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0x28-0x2F&lt;/td&gt;
&lt;td&gt;(padding)&lt;/td&gt;
&lt;td&gt;8字节&lt;/td&gt;
&lt;td&gt;最终内存对齐填充&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;关键特性：&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>iOS 定时器的注意事项</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/timer%E7%9A%84%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/timer%E7%9A%84%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9/</guid><description>&lt;p&gt;iOS 开发中常用的定时器有 NSTimer、CADisplayLink 和 GCD Timer。它们各有特点，但在使用时都有一些需要注意的问题。&lt;/p&gt;
&lt;h2 id="常见定时器类型"&gt;常见定时器类型&lt;/h2&gt;
&lt;h3 id="1-nstimer"&gt;1. NSTimer&lt;/h3&gt;
&lt;p&gt;最常用的定时器，基于 RunLoop 实现：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 自动添加到当前 RunLoop 的 DefaultMode
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NSTimer &lt;span style="color:#f92672"&gt;*&lt;/span&gt;timer &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [NSTimer scheduledTimerWithTimeInterval:&lt;span style="color:#ae81ff"&gt;1.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; target:self
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; selector:&lt;span style="color:#66d9ef"&gt;@selector&lt;/span&gt;(timerFired)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; userInfo:nil
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; repeats:YES];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 手动创建，需要手动添加到 RunLoop
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NSTimer &lt;span style="color:#f92672"&gt;*&lt;/span&gt;timer &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [NSTimer timerWithTimeInterval:&lt;span style="color:#ae81ff"&gt;1.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; target:self
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; selector:&lt;span style="color:#66d9ef"&gt;@selector&lt;/span&gt;(timerFired)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; userInfo:nil
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; repeats:YES];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="2-cadisplaylink"&gt;2. CADisplayLink&lt;/h3&gt;
&lt;p&gt;与屏幕刷新率同步的定时器，适合做动画：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CADisplayLink &lt;span style="color:#f92672"&gt;*&lt;/span&gt;displayLink &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [CADisplayLink displayLinkWithTarget:self
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; selector:&lt;span style="color:#66d9ef"&gt;@selector&lt;/span&gt;(update)];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="3-gcd-timer"&gt;3. GCD Timer&lt;/h3&gt;
&lt;p&gt;不依赖 RunLoop，精度更高：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;dispatch_source_t timer &lt;span style="color:#f92672"&gt;=&lt;/span&gt; dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, dispatch_get_main_queue());
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, &lt;span style="color:#ae81ff"&gt;1.0&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt; NSEC_PER_SEC, &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;dispatch_source_set_event_handler(timer, &lt;span style="color:#f92672"&gt;^&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; NSLog(&lt;span style="color:#e6db74"&gt;@&amp;#34;GCD Timer fired&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;dispatch_resume(timer);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="注意事项一循环引用问题"&gt;注意事项一：循环引用问题&lt;/h2&gt;
&lt;h3 id="问题描述"&gt;问题描述&lt;/h3&gt;
&lt;p&gt;NSTimer 和 CADisplayLink 在使用 target-action 模式时，会强引用 target。如果 target 又持有定时器，就会形成循环引用：&lt;/p&gt;</description></item><item><title>iOS中的内存管理</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/ios%E4%B8%AD%E7%9A%84%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/ios%E4%B8%AD%E7%9A%84%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86/</guid><description>&lt;p&gt;本文将系统介绍iOS中的内存管理机制，从程序内存布局、引用计数原理、ARC机制到系统级内存管理，帮助你建立完整的iOS内存管理知识体系。&lt;/p&gt;
&lt;h2 id="一程序内存布局"&gt;一、程序内存布局&lt;/h2&gt;
&lt;h3 id="内存区域划分"&gt;内存区域划分&lt;/h3&gt;
&lt;p&gt;在iOS应用程序中，内存按照用途和管理方式分为以下几个区域：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;高地址
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;┌─────────────────────────────────────┐
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ 栈区 (Stack) │ ↓ 向低地址增长
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ 局部变量、函数参数、返回地址 │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├─────────────────────────────────────┤
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ↕ │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ 动态分配区 │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ↕ │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├─────────────────────────────────────┤
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ 堆区 (Heap) │ ↑ 向高地址增长
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ 动态分配的对象实例 │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├─────────────────────────────────────┤
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ 全局/静态区 (BSS) │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ 未初始化的全局变量和静态变量 │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├─────────────────────────────────────┤
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ 数据区 (Data) │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ 已初始化的全局变量和静态变量 │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├─────────────────────────────────────┤
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ 常量区 (Rodata) │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ 字符串常量等 │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├─────────────────────────────────────┤
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ 代码区 (Text) │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ 编译后的代码 │
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;└─────────────────────────────────────┘
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;低地址
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;各区域的特点：&lt;/p&gt;</description></item><item><title>iOS中的数据库</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/ios%E4%B8%AD%E7%9A%84%E6%95%B0%E6%8D%AE%E5%BA%93/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/ios%E4%B8%AD%E7%9A%84%E6%95%B0%E6%8D%AE%E5%BA%93/</guid><description>&lt;p&gt;数据持久化是移动端开发的核心能力之一。iOS提供了从轻量级KV存储到完整关系数据库的多层次方案。本文将从底层存储原理出发，系统性地梳理iOS中各类数据库与持久化技术的设计思想、实现机制和适用场景。&lt;/p&gt;
&lt;h2 id="一ios数据持久化方案全景"&gt;一、iOS数据持久化方案全景&lt;/h2&gt;
&lt;p&gt;iOS中常见的数据持久化方案，按数据复杂度和使用场景可分为以下几层：&lt;/p&gt;
&lt;pre class="mermaid"&gt;graph TD
subgraph KV["轻量级KV存储"]
A["UserDefaults&lt;br/&gt;plist序列化"]
B["Keychain&lt;br/&gt;加密存储"]
C["MMKV&lt;br/&gt;mmap + protobuf"]
end
subgraph FILE["文件存储"]
D["plist / JSON"]
E["NSCoding / Codable&lt;br/&gt;归档"]
end
subgraph SQL["关系数据库"]
F["SQLite&lt;br/&gt;C语言API"]
G["FMDB&lt;br/&gt;OC封装"]
H["WCDB&lt;br/&gt;ORM + 加密"]
end
subgraph ORM["ORM框架"]
I["Core Data&lt;br/&gt;Apple官方"]
J["Realm&lt;br/&gt;零拷贝"]
K["SwiftData&lt;br/&gt;Swift原生"]
end
KV --&gt; |"数据结构更复杂"| FILE
FILE --&gt; |"需要结构化查询"| SQL
SQL --&gt; |"需要对象映射"| ORM
&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;方案&lt;/th&gt;
&lt;th&gt;数据模型&lt;/th&gt;
&lt;th&gt;查询能力&lt;/th&gt;
&lt;th&gt;线程安全&lt;/th&gt;
&lt;th&gt;加密&lt;/th&gt;
&lt;th&gt;适用场景&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;UserDefaults&lt;/td&gt;
&lt;td&gt;KV (plist类型)&lt;/td&gt;
&lt;td&gt;Key查找&lt;/td&gt;
&lt;td&gt;线程安全&lt;/td&gt;
&lt;td&gt;无&lt;/td&gt;
&lt;td&gt;用户偏好、简单配置&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Keychain&lt;/td&gt;
&lt;td&gt;KV (Data)&lt;/td&gt;
&lt;td&gt;Key查找&lt;/td&gt;
&lt;td&gt;线程安全&lt;/td&gt;
&lt;td&gt;系统加密&lt;/td&gt;
&lt;td&gt;密码、Token、证书&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MMKV&lt;/td&gt;
&lt;td&gt;KV (protobuf)&lt;/td&gt;
&lt;td&gt;Key查找&lt;/td&gt;
&lt;td&gt;线程安全&lt;/td&gt;
&lt;td&gt;可选AES&lt;/td&gt;
&lt;td&gt;高频读写的KV数据&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;plist/JSON文件&lt;/td&gt;
&lt;td&gt;字典/数组&lt;/td&gt;
&lt;td&gt;无&lt;/td&gt;
&lt;td&gt;不安全&lt;/td&gt;
&lt;td&gt;无&lt;/td&gt;
&lt;td&gt;静态配置、缓存&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NSCoding/Codable&lt;/td&gt;
&lt;td&gt;对象图&lt;/td&gt;
&lt;td&gt;无&lt;/td&gt;
&lt;td&gt;不安全&lt;/td&gt;
&lt;td&gt;无&lt;/td&gt;
&lt;td&gt;对象序列化&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SQLite&lt;/td&gt;
&lt;td&gt;关系表&lt;/td&gt;
&lt;td&gt;SQL&lt;/td&gt;
&lt;td&gt;需手动处理&lt;/td&gt;
&lt;td&gt;可选(SQLCipher)&lt;/td&gt;
&lt;td&gt;结构化数据、复杂查询&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FMDB&lt;/td&gt;
&lt;td&gt;关系表&lt;/td&gt;
&lt;td&gt;SQL&lt;/td&gt;
&lt;td&gt;FMDatabaseQueue&lt;/td&gt;
&lt;td&gt;可选&lt;/td&gt;
&lt;td&gt;SQLite的OC封装&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WCDB&lt;/td&gt;
&lt;td&gt;关系表+ORM&lt;/td&gt;
&lt;td&gt;SQL+ORM&lt;/td&gt;
&lt;td&gt;自动管理&lt;/td&gt;
&lt;td&gt;内置&lt;/td&gt;
&lt;td&gt;高性能结构化存储&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Core Data&lt;/td&gt;
&lt;td&gt;对象图&lt;/td&gt;
&lt;td&gt;NSPredicate&lt;/td&gt;
&lt;td&gt;NSManagedObjectContext&lt;/td&gt;
&lt;td&gt;无&lt;/td&gt;
&lt;td&gt;复杂对象关系&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Realm&lt;/td&gt;
&lt;td&gt;对象&lt;/td&gt;
&lt;td&gt;类型安全查询&lt;/td&gt;
&lt;td&gt;对象冻结&lt;/td&gt;
&lt;td&gt;可选AES&lt;/td&gt;
&lt;td&gt;高性能对象存储&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SwiftData&lt;/td&gt;
&lt;td&gt;Swift对象&lt;/td&gt;
&lt;td&gt;#Predicate宏&lt;/td&gt;
&lt;td&gt;ModelContext&lt;/td&gt;
&lt;td&gt;无&lt;/td&gt;
&lt;td&gt;Swift原生数据持久化&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="二轻量级kv存储"&gt;二、轻量级KV存储&lt;/h2&gt;
&lt;h3 id="21-userdefaults"&gt;2.1 UserDefaults&lt;/h3&gt;
&lt;p&gt;UserDefaults是iOS最常用的轻量级存储方案，底层将数据以plist格式序列化到磁盘。&lt;/p&gt;</description></item><item><title>iOS反射</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/ios%E5%8F%8D%E5%B0%84/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/ios%E5%8F%8D%E5%B0%84/</guid><description>&lt;p&gt;反射（Reflection）是指程序在运行时检查、访问和修改自身结构（类型、属性、方法等）的能力。在 iOS 开发中，Objective-C 和 Swift 分别提供了不同层次的反射支持：OC 依赖 Runtime 提供完整的动态反射能力，Swift 则通过 Mirror 提供只读的内省能力。&lt;/p&gt;
&lt;h2 id="objective-c-的反射能力"&gt;Objective-C 的反射能力&lt;/h2&gt;
&lt;p&gt;Objective-C 的反射能力完全建立在 Runtime 之上。Runtime 在运行时维护了完整的类型元数据（类对象、元类对象、方法列表、属性列表、成员变量列表、协议列表等），并通过一系列 C 函数 API 暴露给开发者，使得程序可以在运行时动态地查询和修改几乎所有类型信息。&lt;/p&gt;
&lt;p&gt;关于 Runtime 的消息发送、消息转发、Method Swizzling、关联对象等核心能力，请参考 &lt;a href="https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/runtime/"&gt;runtime&lt;/a&gt;。本节聚焦于 Runtime 中与&amp;quot;反射&amp;quot;直接相关的能力——即运行时的类型内省和动态操作。&lt;/p&gt;
&lt;h3 id="类型内省"&gt;类型内省&lt;/h3&gt;
&lt;p&gt;类型内省（Introspection）是反射中最基础的能力——在运行时查询一个对象的类型信息。&lt;/p&gt;
&lt;h4 id="nsobject-提供的内省方法"&gt;NSObject 提供的内省方法&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;NSObject&lt;/code&gt; 定义了一组内省方法，这些方法底层都依赖 Runtime 的 isa 指针和类型元数据来实现：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;id&lt;/span&gt; obj &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [[NSMutableArray alloc] init];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 类型判断
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[obj isKindOfClass:[NSArray &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt;]]; &lt;span style="color:#75715e"&gt;// YES — 判断是否是某个类或其子类的实例
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[obj isMemberOfClass:[NSMutableArray &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt;]]; &lt;span style="color:#75715e"&gt;// YES — 判断是否是某个类的直接实例
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[obj conformsToProtocol:@protocol(NSCoding)]; &lt;span style="color:#75715e"&gt;// YES — 判断是否遵循某个协议
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 方法响应检查
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[obj respondsToSelector:&lt;span style="color:#66d9ef"&gt;@selector&lt;/span&gt;(addObject:)]; &lt;span style="color:#75715e"&gt;// YES — 判断是否能响应某个消息
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 获取类型信息
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NSStringFromClass([obj &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt;]); &lt;span style="color:#75715e"&gt;// @&amp;#34;__NSArrayM&amp;#34;（真实的私有子类名）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NSStringFromSelector(&lt;span style="color:#66d9ef"&gt;@selector&lt;/span&gt;(count)); &lt;span style="color:#75715e"&gt;// @&amp;#34;count&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;需要注意 &lt;code&gt;isKindOfClass:&lt;/code&gt; 和 &lt;code&gt;isMemberOfClass:&lt;/code&gt; 的区别：前者沿继承链向上查找，后者只比较当前类。另外，&lt;code&gt;[obj class]&lt;/code&gt; 返回的可能是私有子类（如类簇 &lt;code&gt;NSArray&lt;/code&gt; 的实际类是 &lt;code&gt;__NSArrayI&lt;/code&gt; 或 &lt;code&gt;__NSArrayM&lt;/code&gt;），而 &lt;code&gt;object_getClass(obj)&lt;/code&gt; 能获取真正的 isa 指向的类（KVO 场景下会是 &lt;code&gt;NSKVONotifying_&lt;/code&gt; 前缀的子类）。&lt;/p&gt;</description></item><item><title>iOS编译原理</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/ios%E7%BC%96%E8%AF%91%E5%8E%9F%E7%90%86/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/ios%E7%BC%96%E8%AF%91%E5%8E%9F%E7%90%86/</guid><description>&lt;h2 id="编译器架构llvm-与-clang"&gt;编译器架构：LLVM 与 Clang&lt;/h2&gt;
&lt;p&gt;iOS 开发中的两种主要语言 Objective-C 和 Swift 都基于 LLVM 编译器基础设施。理解 LLVM 的架构是理解 iOS 编译原理的基础。&lt;/p&gt;
&lt;h3 id="llvm-的三段式架构"&gt;LLVM 的三段式架构&lt;/h3&gt;
&lt;p&gt;LLVM 采用经典的&lt;strong&gt;前端-中间表示-后端&lt;/strong&gt;三段式设计，将编译过程解耦为三个独立的阶段：&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart LR
subgraph Frontend["前端（Frontend）"]
direction TB
A1["Clang（OC/C/C++）"]
A2["Swift 前端"]
end
subgraph Middle["中间表示"]
direction TB
B1["LLVM IR"]
end
subgraph Backend["后端（Backend）"]
direction TB
C1["arm64（iOS真机）"]
C2["x86_64（模拟器）"]
end
A1 --&gt; B1
A2 --&gt; B1
B1 --&gt; C1
B1 --&gt; C2
&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;阶段&lt;/th&gt;
&lt;th&gt;职责&lt;/th&gt;
&lt;th&gt;iOS 中的实现&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;前端（Frontend）&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;词法分析、语法分析、语义分析，将源码转换为中间表示&lt;/td&gt;
&lt;td&gt;Clang（OC/C/C++）、Swift 前端&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;中间表示（IR）&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;与语言无关、与平台无关的中间形式，承载优化&lt;/td&gt;
&lt;td&gt;LLVM IR（Swift 还有额外的 SIL 层）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;后端（Backend）&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;将 IR 转换为目标平台的机器码&lt;/td&gt;
&lt;td&gt;arm64（真机）、x86_64（Intel 模拟器）&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;三段式架构的核心优势是&lt;strong&gt;解耦&lt;/strong&gt;：新增一门语言只需实现一个前端，新增一个目标平台只需实现一个后端，所有语言和平台共享同一套优化基础设施。这正是 Apple 能同时支持 OC 和 Swift 两种语言、多种架构（arm64、x86_64）的技术基础。&lt;/p&gt;</description></item><item><title>+load与+initialize的区别</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/load%E4%B8%8Einitialize%E7%9A%84%E5%8C%BA%E5%88%AB/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/load%E4%B8%8Einitialize%E7%9A%84%E5%8C%BA%E5%88%AB/</guid><description>&lt;p&gt;&lt;code&gt;+load&lt;/code&gt;和&lt;code&gt;+initialize&lt;/code&gt;是Objective-C中两个特殊的类方法，它们都会被Runtime自动调用，但调用时机、调用方式和使用场景有很大区别。理解它们的差异对于iOS开发和性能优化非常重要。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="基本定义"&gt;基本定义&lt;/h2&gt;
&lt;h3 id="load方法"&gt;+load方法&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;+load&lt;/code&gt;方法在类被加载到内存时由Runtime自动调用，发生在main函数执行之前。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@implementation&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;MyClass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;+ (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;load&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; NSLog(&lt;span style="color:#e6db74"&gt;@&amp;#34;MyClass loaded&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="initialize方法"&gt;+initialize方法&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;+initialize&lt;/code&gt;方法在类第一次收到消息时由Runtime自动调用，是一种懒加载机制。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@implementation&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;MyClass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;+ (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;initialize&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; NSLog(&lt;span style="color:#e6db74"&gt;@&amp;#34;MyClass initialized&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="核心区别对比"&gt;核心区别对比&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;特性&lt;/th&gt;
&lt;th&gt;+load&lt;/th&gt;
&lt;th&gt;+initialize&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;调用时机&lt;/td&gt;
&lt;td&gt;main函数之前，类加载时&lt;/td&gt;
&lt;td&gt;类首次收到消息时&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;调用方式&lt;/td&gt;
&lt;td&gt;直接调用函数指针&lt;/td&gt;
&lt;td&gt;通过objc_msgSend&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;调用次数&lt;/td&gt;
&lt;td&gt;每个类只调用一次&lt;/td&gt;
&lt;td&gt;可能被调用多次&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;是否阻塞启动&lt;/td&gt;
&lt;td&gt;是&lt;/td&gt;
&lt;td&gt;否&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;是否需要显式调用父类&lt;/td&gt;
&lt;td&gt;否，自动调用&lt;/td&gt;
&lt;td&gt;否，自动调用&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Category的行为&lt;/td&gt;
&lt;td&gt;都会被调用&lt;/td&gt;
&lt;td&gt;会覆盖主类实现&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;线程安全&lt;/td&gt;
&lt;td&gt;是&lt;/td&gt;
&lt;td&gt;是&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;调用顺序&lt;/td&gt;
&lt;td&gt;父类 -&amp;gt; 子类 -&amp;gt; Category&lt;/td&gt;
&lt;td&gt;父类 -&amp;gt; 子类&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;未实现时的行为&lt;/td&gt;
&lt;td&gt;不调用&lt;/td&gt;
&lt;td&gt;可能调用父类实现&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="调用时机详解"&gt;调用时机详解&lt;/h2&gt;
&lt;h3 id="load的调用时机"&gt;+load的调用时机&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;+load&lt;/code&gt;的调用发生在dyld加载镜像的过程中：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;dyld加载Mach&lt;span style="color:#f92672"&gt;-&lt;/span&gt;O
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;↓&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;映射到内存&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;↓&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;读取&lt;/span&gt;__DATA段中的__objc_nlclslist&lt;span style="color:#960050;background-color:#1e0010"&gt;（非懒加载类列表）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;↓&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;调用所有类的&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;load方法
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;↓&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;读取&lt;/span&gt;__objc_nlcatlist&lt;span style="color:#960050;background-color:#1e0010"&gt;（非懒加载分类列表）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;↓&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;调用所有分类的&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;load方法
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;↓&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;main()&lt;span style="color:#960050;background-color:#1e0010"&gt;函数执行&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="initialize的调用时机"&gt;+initialize的调用时机&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;+initialize&lt;/code&gt;在类第一次收到消息时调用：&lt;/p&gt;</description></item><item><title>mmap详解</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/mmap%E8%AF%A6%E8%A7%A3/</link><pubDate>Thu, 07 May 2026 10:26:09 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/mmap%E8%AF%A6%E8%A7%A3/</guid><description>&lt;p&gt;mmap（Memory-mapped file，内存映射文件）是一种将文件或设备映射到进程地址空间的技术。通过mmap，可以像操作内存一样操作文件，是iOS开发中实现高性能IO的重要手段。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="基本概念"&gt;基本概念&lt;/h2&gt;
&lt;h3 id="什么是mmap"&gt;什么是mmap&lt;/h3&gt;
&lt;p&gt;mmap是一个POSIX系统调用，它在进程的虚拟地址空间中创建一个映射，将文件内容映射到内存地址。映射建立后，对该内存区域的读写操作会直接反映到文件上。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;文件映射&lt;/strong&gt;：将磁盘上的普通文件映射到内存，用于高效读写文件内容（iOS开发中最常用）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;设备映射&lt;/strong&gt;：将硬件设备的I/O内存（如显卡显存、网卡缓冲区）映射到用户空间，让程序可以像读写内存一样直接与硬件交互，常用于驱动开发和嵌入式系统&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="mermaid"&gt;flowchart LR
subgraph traditional["传统文件IO (read/write)"]
direction LR
U1["用户缓冲区"] &lt;-- "② 数据拷贝" --&gt; K1["内核缓冲区"]
K1 &lt;-- "① 磁盘读取" --&gt; F1["磁盘文件"]
end
subgraph mmap_io["mmap 内存映射"]
direction LR
U2["虚拟地址空间&lt;br/&gt;映射区域"] &lt;-. "直接映射&lt;br/&gt;零拷贝" .-&gt; F2["磁盘文件"]
end
traditional ~~~ mmap_io
&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;方式&lt;/th&gt;
&lt;th&gt;数据流向&lt;/th&gt;
&lt;th&gt;拷贝次数&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;传统IO&lt;/td&gt;
&lt;td&gt;磁盘 → 内核缓冲 → 用户缓冲&lt;/td&gt;
&lt;td&gt;2次&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;mmap&lt;/td&gt;
&lt;td&gt;磁盘 ↔ 映射区域（直接访问）&lt;/td&gt;
&lt;td&gt;0次&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="mmap的工作原理"&gt;mmap的工作原理&lt;/h3&gt;
&lt;pre class="mermaid"&gt;flowchart TD
A["调用mmap()"] --&gt; B["内核在进程虚拟地址空间&lt;br/&gt;分配一段连续地址"]
B --&gt; C["建立虚拟地址到文件的映射关系&lt;br/&gt;（页表项指向文件页）"]
C --&gt; D["返回映射区域的起始地址"]
D --&gt; E["进程访问映射地址"]
E --&gt; F{"页面是否在内存中?"}
F -- 否 --&gt; G["触发缺页中断&lt;br/&gt;(Page Fault)"]
G --&gt; H["内核从磁盘读取对应页面&lt;br/&gt;到物理内存"]
H --&gt; I["更新页表，建立映射"]
I --&gt; J["进程继续访问"]
F -- 是 --&gt; J
J --&gt; K["读写操作直接作用于内存"]
K --&gt; L["内核适时将脏页&lt;br/&gt;写回磁盘"]
&lt;/pre&gt;
&lt;hr&gt;
&lt;h2 id="api详解"&gt;API详解&lt;/h2&gt;
&lt;h3 id="mmap函数原型"&gt;mmap函数原型&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;sys/mman.h&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;mmap&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;addr, &lt;span style="color:#75715e"&gt;// 建议的映射起始地址，通常传NULL让系统决定
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;size_t&lt;/span&gt; length, &lt;span style="color:#75715e"&gt;// 映射区域的长度（字节）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; prot, &lt;span style="color:#75715e"&gt;// 内存保护标志（可读/可写/可执行）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; flags, &lt;span style="color:#75715e"&gt;// 映射类型标志
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; fd, &lt;span style="color:#75715e"&gt;// 文件描述符
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;off_t&lt;/span&gt; offset &lt;span style="color:#75715e"&gt;// 文件偏移量（必须是页大小的整数倍）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 返回值：成功返回映射区域的起始地址，失败返回MAP_FAILED
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="参数详解"&gt;参数详解&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;prot（内存保护标志）&lt;/strong&gt;：&lt;/p&gt;</description></item><item><title>RunLoop</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/runloop/</link><pubDate>Wed, 27 May 2026 22:24:03 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/runloop/</guid><description>&lt;p&gt;RunLoop 是 iOS/macOS 中用于管理线程的事件循环机制。它的核心作用是让线程在有任务时处理任务，没有任务时进入休眠状态，从而避免线程退出并节省 CPU 资源。&lt;/p&gt;
&lt;p&gt;简单来说，RunLoop 就是一个 do-while 循环：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 伪代码
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;CFRunLoopRun&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 处理各种事件源
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 如果没有事件，线程休眠
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 有事件时被唤醒处理
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; } &lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; (running);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="runloop-与线程的关系"&gt;RunLoop 与线程的关系&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;每个线程都有唯一对应的 RunLoop 对象&lt;/li&gt;
&lt;li&gt;主线程和子线程的 RunLoop 都采用懒加载机制，在第一次获取时才创建&lt;/li&gt;
&lt;li&gt;主线程的 RunLoop 由 &lt;code&gt;UIApplicationMain&lt;/code&gt; 内部首次获取并启动（调用链：&lt;code&gt;UIApplicationMain&lt;/code&gt; → &lt;code&gt;GSEventRunModal&lt;/code&gt; → &lt;code&gt;CFRunLoopRunSpecific&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;RunLoop 与线程是一一对应的，存储在一个全局字典（&lt;code&gt;__CFRunLoops&lt;/code&gt;）中&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 获取当前线程的 RunLoop
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CFRunLoopRef runLoop &lt;span style="color:#f92672"&gt;=&lt;/span&gt; CFRunLoopGetCurrent();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NSRunLoop &lt;span style="color:#f92672"&gt;*&lt;/span&gt;runLoop &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [NSRunLoop currentRunLoop];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 获取主线程的 RunLoop
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CFRunLoopRef mainRunLoop &lt;span style="color:#f92672"&gt;=&lt;/span&gt; CFRunLoopGetMain();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NSRunLoop &lt;span style="color:#f92672"&gt;*&lt;/span&gt;mainRunLoop &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [NSRunLoop mainRunLoop];
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="runloop-的核心组成"&gt;RunLoop 的核心组成&lt;/h2&gt;
&lt;p&gt;RunLoop 包含以下几个核心概念：&lt;/p&gt;
&lt;h3 id="1-runloop-对象cfrunloopref"&gt;1. RunLoop 对象（CFRunLoopRef）&lt;/h3&gt;
&lt;p&gt;RunLoop 对象本身，管理整个事件循环。在代码层面对应 &lt;code&gt;CFRunLoopRef&lt;/code&gt; 类型。&lt;/p&gt;</description></item><item><title>Runtime</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/runtime/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/runtime/</guid><description>&lt;h2 id="什么是-runtime"&gt;什么是 Runtime&lt;/h2&gt;
&lt;p&gt;Runtime 是 Objective-C 的运行时系统，是一套底层的 C 语言 API。Objective-C 是一门动态语言，很多操作都是在运行时而非编译时决定的，这一切都依赖于 Runtime。&lt;/p&gt;
&lt;p&gt;Runtime 提供的核心能力：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;消息发送与转发&lt;/li&gt;
&lt;li&gt;方法交换（Method Swizzling）&lt;/li&gt;
&lt;li&gt;关联对象（Associated Objects）&lt;/li&gt;
&lt;li&gt;动态创建类和对象&lt;/li&gt;
&lt;li&gt;动态添加和修改方法、属性&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;关于对象、类、isa 指针等底层数据结构的详细介绍，请参考 &lt;a href="https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/objective-c%E5%BA%95%E5%B1%82%E5%8E%9F%E7%90%86-nsobject/"&gt;Objective-C底层原理-NSObject&lt;/a&gt;。本文专注于 Runtime 的动态能力和实际应用。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="消息发送机制"&gt;消息发送机制&lt;/h2&gt;
&lt;p&gt;Objective-C 的消息发送机制是其动态性的核心体现。与 Swift 支持静态派发不同，Objective-C 的方法调用都是动态消息派发。更多关于两者的对比，请参考 &lt;a href="https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/objective-c%E4%B8%8Eswift%E5%8C%BA%E5%88%AB/"&gt;Objective-C与Swift区别&lt;/a&gt;。&lt;/p&gt;
&lt;h3 id="objc_msgsend"&gt;objc_msgSend&lt;/h3&gt;
&lt;p&gt;Objective-C 的方法调用本质上是消息发送，编译器会将方法调用转换为 &lt;code&gt;objc_msgSend&lt;/code&gt; 函数：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 源代码
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[obj doSomething];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 编译后
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;objc_msgSend(obj, &lt;span style="color:#66d9ef"&gt;@selector&lt;/span&gt;(doSomething));
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="消息发送流程"&gt;消息发送流程&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;1. 检查 receiver 是否为 nil，如果是则直接返回
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2. 通过 isa 找到 receiver 的类对象
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;3. 在类对象的方法缓存（cache_t）中查找方法
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;4. 如果缓存命中，直接调用方法实现（IMP）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;5. 如果缓存未命中，在类对象的方法列表中查找
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;6. 如果找到，缓存方法并调用
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;7. 如果未找到，沿着 superclass 链向上查找
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;8. 如果最终未找到，进入消息转发流程
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="方法缓存"&gt;方法缓存&lt;/h3&gt;
&lt;p&gt;为了提高消息发送效率，Runtime 在类对象中使用哈希表缓存最近调用的方法：&lt;/p&gt;</description></item><item><title>static关键字详解</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/static%E5%85%B3%E9%94%AE%E5%AD%97%E8%AF%A6%E8%A7%A3/</link><pubDate>Sun, 03 May 2026 23:11:47 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/static%E5%85%B3%E9%94%AE%E5%AD%97%E8%AF%A6%E8%A7%A3/</guid><description>&lt;h2 id="基础概念"&gt;基础概念&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;static&lt;/code&gt; 是 C 语言定义的存储类说明符（Storage Class Specifier），Objective-C 和 Swift 中均有使用，但语义有所扩展。它的核心作用可以归纳为两点：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;改变存储位置&lt;/strong&gt;：将局部变量从栈区移到数据段，使其在函数返回后依然存活&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;限制链接可见性&lt;/strong&gt;：将全局变量或函数的链接属性从 external 改为 internal，使其仅在当前编译单元（&lt;code&gt;.m&lt;/code&gt; 文件）内可见&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="mermaid"&gt;flowchart TD
A["static 关键字"] --&gt; B["修饰局部变量"]
A --&gt; C["修饰全局变量"]
A --&gt; D["修饰函数"]
A --&gt; E["Swift 中的 static"]
B --&gt; B1["存储位置：栈 → 数据段"]
B --&gt; B2["生命周期：函数作用域 → 整个进程"]
B --&gt; B3["作用域不变：仍限于函数内"]
C --&gt; C1["存储位置不变：仍在数据段"]
C --&gt; C2["链接属性：external → internal"]
C --&gt; C3["作用域缩小：全局 → 当前文件"]
D --&gt; D1["存储位置不变：仍在代码段"]
D --&gt; D2["链接属性：external → internal"]
D --&gt; D3["作用域缩小：全局 → 当前文件"]
&lt;/pre&gt;
&lt;h2 id="一静态局部变量"&gt;一、静态局部变量&lt;/h2&gt;
&lt;h3 id="基本用法"&gt;基本用法&lt;/h3&gt;
&lt;p&gt;在函数或方法内部用 &lt;code&gt;static&lt;/code&gt; 修饰局部变量，使其只初始化一次，后续调用保留上次的值。&lt;/p&gt;</description></item><item><title>weak详解</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/weak%E8%AF%A6%E8%A7%A3/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/weak%E8%AF%A6%E8%A7%A3/</guid><description>&lt;p&gt;本文将深入探讨iOS中&lt;code&gt;weak&lt;/code&gt;引用的实现原理，包括底层数据结构、核心函数实现、生命周期管理，以及&lt;code&gt;weak&lt;/code&gt;、&lt;code&gt;unowned&lt;/code&gt;、&lt;code&gt;unsafe_unretained&lt;/code&gt;三者的对比。&lt;/p&gt;
&lt;h2 id="weak的基本概念"&gt;weak的基本概念&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;weak&lt;/code&gt;是一种弱引用修饰符，它&lt;strong&gt;不会增加对象的引用计数&lt;/strong&gt;，也就是说不会持有对象。当对象被释放时，所有指向该对象的&lt;code&gt;weak&lt;/code&gt;引用会&lt;strong&gt;自动被置为nil&lt;/strong&gt;，这是&lt;code&gt;weak&lt;/code&gt;最核心的特性。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Objective-C中使用weak
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@property&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;nonatomic&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;weak&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;id&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;SomeDelegate&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; delegate;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;__weak&lt;/span&gt; NSObject &lt;span style="color:#f92672"&gt;*&lt;/span&gt;weakObj &lt;span style="color:#f92672"&gt;=&lt;/span&gt; strongObj;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Swift中使用weak&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;weak&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; delegate: SomeDelegate?
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;weak&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; weakObj = strongObj
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="weak的底层数据结构"&gt;weak的底层数据结构&lt;/h2&gt;
&lt;p&gt;要理解&lt;code&gt;weak&lt;/code&gt;的实现原理，首先需要了解几个核心数据结构。&lt;/p&gt;
&lt;h3 id="sidetable"&gt;SideTable&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;SideTable&lt;/code&gt;是Runtime中非常重要的数据结构。关于SideTable在引用计数存储中的作用，请参考&lt;a href="https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/ios%E4%B8%AD%E7%9A%84%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86/#%E4%BE%A7%E8%A1%A8%E5%AD%98%E5%82%A8sidetable"&gt;iOS中的内存管理-侧表存储&lt;/a&gt;。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; SideTable {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; os_unfair_lock slock; &lt;span style="color:#75715e"&gt;// 锁，保证线程安全
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; RefcountMap refcnts; &lt;span style="color:#75715e"&gt;// 引用计数哈希表
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;weak_table_t&lt;/span&gt; weak_table; &lt;span style="color:#75715e"&gt;// 弱引用表
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;系统维护了一个&lt;strong&gt;固定大小&lt;/strong&gt;的&lt;code&gt;SideTable&lt;/code&gt;数组，称为&lt;code&gt;StripedMap&lt;/code&gt;。通过对对象地址做哈希和取模来定位对应的&lt;code&gt;SideTable&lt;/code&gt;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 通过对象地址获取对应的SideTable
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; SideTable&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt; table &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;SideTables&lt;/span&gt;()[obj];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 内部等效逻辑：index = hash(obj) % StripeCount
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// StripeCount为StripedMap的大小
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;由于对象数量远大于&lt;code&gt;SideTable&lt;/code&gt;数量，&lt;strong&gt;多个对象会被映射到同一个&lt;code&gt;SideTable&lt;/code&gt;&lt;/strong&gt;，这类似于哈希表中的哈希冲突。这种设计的核心目的是&lt;strong&gt;分散锁竞争&lt;/strong&gt;——每个&lt;code&gt;SideTable&lt;/code&gt;拥有独立的锁，不同&lt;code&gt;SideTable&lt;/code&gt;上的操作可以并行执行，相比单一全局表大幅提升了多线程性能。&lt;/p&gt;
&lt;h3 id="weak_table_t"&gt;weak_table_t&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;weak_table_t&lt;/code&gt;是存储弱引用关系的哈希表，采用 &lt;strong&gt;开放寻址法（线性探测）&lt;/strong&gt; 解决哈希冲突：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;weak_table_t&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;weak_entry_t&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;weak_entries; &lt;span style="color:#75715e"&gt;// 连续分配的数组，作为开放寻址哈希表的底层存储
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;size_t&lt;/span&gt; num_entries; &lt;span style="color:#75715e"&gt;// 当前已使用的条目数量
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;uintptr_t&lt;/span&gt; mask; &lt;span style="color:#75715e"&gt;// 容量掩码（= 数组容量 - 1），用于 hash &amp;amp; mask 快速取模
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;uintptr_t&lt;/span&gt; max_hash_displacement; &lt;span style="color:#75715e"&gt;// 最大哈希冲突偏移量
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;虽然 &lt;code&gt;weak_entries&lt;/code&gt; 的类型是 &lt;code&gt;weak_entry_t *&lt;/code&gt;（即一块连续内存），但元素&lt;strong&gt;不是按顺序填入&lt;/strong&gt;的——插入时通过 &lt;code&gt;hash(referent地址) &amp;amp; mask&lt;/code&gt; 计算目标槽位，冲突时向后线性探测。因此它本质上是一个&lt;strong&gt;用数组实现的开放寻址哈希表&lt;/strong&gt;，而非普通的顺序数组。&lt;/p&gt;</description></item><item><title>值类型和引用类型的区别</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/%E5%80%BC%E7%B1%BB%E5%9E%8B%E5%92%8C%E5%BC%95%E7%94%A8%E7%B1%BB%E5%9E%8B%E7%9A%84%E5%8C%BA%E5%88%AB/</link><pubDate>Sun, 10 May 2026 22:25:41 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/%E5%80%BC%E7%B1%BB%E5%9E%8B%E5%92%8C%E5%BC%95%E7%94%A8%E7%B1%BB%E5%9E%8B%E7%9A%84%E5%8C%BA%E5%88%AB/</guid><description>&lt;h2 id="定义"&gt;定义&lt;/h2&gt;
&lt;h3 id="值类型"&gt;值类型&lt;/h3&gt;
&lt;p&gt;值类型是指变量直接存储自身字段或描述信息的类型。值类型具有值语义，当将一个值类型变量赋值给另一个变量时，语义上会得到一份独立的值；底层是否立即复制完整数据，取决于编译器优化和写时拷贝等实现。&lt;/p&gt;
&lt;h3 id="引用类型"&gt;引用类型&lt;/h3&gt;
&lt;p&gt;引用类型是指变量存储的是指向数据在内存中位置的引用（指针）。当将一个引用类型变量赋值给另一个变量时，两个变量指向同一块内存区域。&lt;/p&gt;
&lt;h2 id="objective-c中的类型分类"&gt;Objective-C中的类型分类&lt;/h2&gt;
&lt;p&gt;在Objective-C中：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;值类型&lt;/strong&gt;：基础数据类型（int、float、double、BOOL、char等）、结构体（struct）、枚举（enum）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;引用类型&lt;/strong&gt;：除基础数据类型之外的大部分类型，包括NSObject及其子类（NSString、NSArray、NSDictionary、自定义类等）&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="swift中的类型分类"&gt;Swift中的类型分类&lt;/h2&gt;
&lt;p&gt;Swift对类型的分类更加清晰：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;值类型&lt;/strong&gt;：基础数据类型（Int、Float、Double、Bool等）、字符串（String）、结构体（Struct）、枚举（Enum）、数组（Array）、字典（Dictionary）、集合（Set）等&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;引用类型&lt;/strong&gt;：类（Class）、闭包（Closure）、Actor等&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="拷贝机制差异"&gt;拷贝机制差异&lt;/h2&gt;
&lt;h3 id="值类型---值语义拷贝"&gt;值类型 - 值语义拷贝&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;每个值类型变量都有自己的字段存储&lt;/li&gt;
&lt;li&gt;对一个变量的操作不会影响另一个变量&lt;/li&gt;
&lt;li&gt;赋值语义上会得到独立副本；如果字段是引用类型，复制的是引用本身，底层也可能通过写时拷贝延迟真正的数据复制&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="引用类型---浅拷贝"&gt;引用类型 - 浅拷贝&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;引用类型在内存中有一个指向该位置的引用&lt;/li&gt;
&lt;li&gt;引用类型的变量可以指向相同类型的数据&lt;/li&gt;
&lt;li&gt;对一个变量进行的操作会影响另一变量所指向的数据&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="内存分配机制"&gt;内存分配机制&lt;/h2&gt;
&lt;p&gt;需要注意：&lt;strong&gt;值类型/引用类型描述的是语义模型，不等价于栈/堆分配规则&lt;/strong&gt;。Swift编译器会根据生命周期、逃逸分析、优化级别、协议类型包装、集合存储等因素决定具体放在哪里。&lt;/p&gt;
&lt;p&gt;理解Swift对象和字段的内存位置，可以先记住三个规则：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;class实例本体&lt;/strong&gt;通常在堆上，通过引用计数管理生命周期&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;struct/enum的字段&lt;/strong&gt;通常内联存储在这个值本身所在的位置&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;class类型的字段&lt;/strong&gt;存储的是对象引用，也就是一个指针，真实class实例仍然在堆上&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="常见存储位置"&gt;常见存储位置&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;局部值类型变量&lt;/strong&gt;：生命周期明确、未逃逸时，通常可以放在当前线程的栈区，甚至被优化到寄存器中&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;class实例&lt;/strong&gt;：实例本体在堆区，局部变量中保存的是指向堆对象的引用&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;class里的struct属性&lt;/strong&gt;：struct属性内联存储在class实例这块堆内存中&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;struct里的class属性&lt;/strong&gt;：struct内部只保存class引用，真实class实例仍然在堆上&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;被逃逸闭包捕获的值类型&lt;/strong&gt;可能随闭包上下文一起存储在堆区&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Array、Dictionary、Set、String等写时拷贝值类型&lt;/strong&gt;通常只有一小段描述信息是值本身，真实元素或字符缓冲区可能在堆上&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;协议类型（existential container）持有大值类型&lt;/strong&gt;时，如果超过存在容器的内联缓冲区大小，会使用堆分配&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;indirect enum&lt;/strong&gt;的间接关联值会通过堆上的盒子存储，常见于递归枚举&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;全局变量、静态变量&lt;/strong&gt;不属于栈区，也不是普通意义上的堆对象，它们通常位于全局/静态存储区&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;栈区内存分配和销毁通常只需移动栈顶指针，成本较低；堆区更动态，但分配、释放和引用计数维护都有额外成本。&lt;/p&gt;
&lt;h3 id="struct中包含class属性"&gt;struct中包含class属性&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Dog&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; name: String
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;init&lt;/span&gt;(name: String) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;self&lt;/span&gt;.name = name
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Person&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; age: Int
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; dog: Dog
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; p1 = Person(age: &lt;span style="color:#ae81ff"&gt;18&lt;/span&gt;, dog: Dog(name: &lt;span style="color:#e6db74"&gt;&amp;#34;Lucky&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; p2 = p1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;p2.age = &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;p2.dog.name = &lt;span style="color:#e6db74"&gt;&amp;#34;Max&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print(p1.age) &lt;span style="color:#75715e"&gt;// 18&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print(p1.dog.name) &lt;span style="color:#75715e"&gt;// Max&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;内存关系可以近似理解为：&lt;/p&gt;</description></item><item><title>iOS响应者链与事件处理机制</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/%E5%93%8D%E5%BA%94%E8%80%85%E9%93%BE/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/%E5%93%8D%E5%BA%94%E8%80%85%E9%93%BE/</guid><description>&lt;p&gt;当手指触碰iPhone屏幕上的一个按钮时，背后经历了从硬件感知、系统传递、命中测试、事件分发到最终响应的完整链路。本文将系统性地拆解iOS事件处理机制的每个环节。&lt;/p&gt;
&lt;h2 id="一响应者与响应者链"&gt;一、响应者与响应者链&lt;/h2&gt;
&lt;p&gt;理解事件处理的前提是理解&amp;quot;谁有能力处理事件&amp;quot;。在iOS中，这个问题的答案是 &lt;strong&gt;响应者（Responder）&lt;/strong&gt;。&lt;/p&gt;
&lt;h3 id="11-uiresponder"&gt;1.1 UIResponder&lt;/h3&gt;
&lt;p&gt;所有能够接收并处理事件的对象都继承自 &lt;code&gt;UIResponder&lt;/code&gt;：&lt;/p&gt;
&lt;pre class="mermaid"&gt;classDiagram
NSObject &lt;|-- UIResponder
UIResponder &lt;|-- UIView
UIResponder &lt;|-- UIViewController
UIResponder &lt;|-- UIApplication
UIView &lt;|-- UIWindow
UIView &lt;|-- UIControl
UIView &lt;|-- UIScrollView
UIControl &lt;|-- UIButton
UIControl &lt;|-- UISlider
UIScrollView &lt;|-- UITableView
class UIResponder {
+nextResponder: UIResponder?
+touchesBegan(touches, event)
+touchesMoved(touches, event)
+touchesEnded(touches, event)
+touchesCancelled(touches, event)
}
&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;UIResponder&lt;/code&gt; 定义了处理触摸事件的四个核心方法：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;touchesBegan:&lt;/span&gt;(NSSet&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;UITouch &lt;span style="color:#f92672"&gt;*&amp;gt;&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)touches &lt;span style="color:#a6e22e"&gt;withEvent:&lt;/span&gt;(UIEvent &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)event;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;touchesMoved:&lt;/span&gt;(NSSet&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;UITouch &lt;span style="color:#f92672"&gt;*&amp;gt;&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)touches &lt;span style="color:#a6e22e"&gt;withEvent:&lt;/span&gt;(UIEvent &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)event;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;touchesEnded:&lt;/span&gt;(NSSet&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;UITouch &lt;span style="color:#f92672"&gt;*&amp;gt;&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)touches &lt;span style="color:#a6e22e"&gt;withEvent:&lt;/span&gt;(UIEvent &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)event;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;touchesCancelled:&lt;/span&gt;(NSSet&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;UITouch &lt;span style="color:#f92672"&gt;*&amp;gt;&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)touches &lt;span style="color:#a6e22e"&gt;withEvent:&lt;/span&gt;(UIEvent &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)event;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="12-nextresponder与响应者链"&gt;1.2 nextResponder与响应者链&lt;/h3&gt;
&lt;p&gt;每个 &lt;code&gt;UIResponder&lt;/code&gt; 都有一个 &lt;code&gt;nextResponder&lt;/code&gt; 属性，指向&amp;quot;下一个响应者&amp;quot;。所有响应者通过这个属性串联成一条 &lt;strong&gt;响应者链（Responder Chain）&lt;/strong&gt;。&lt;/p&gt;</description></item><item><title>iOS多线程编程</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/%E5%A4%9A%E7%BA%BF%E7%A8%8B/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/%E5%A4%9A%E7%BA%BF%E7%A8%8B/</guid><description>&lt;p&gt;iOS多线程方案对比&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;方案&lt;/th&gt;
&lt;th&gt;简介&lt;/th&gt;
&lt;th&gt;语言&lt;/th&gt;
&lt;th&gt;生命周期管理&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;pthread&lt;/td&gt;
&lt;td&gt;POSIX标准的多线程API&lt;/td&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;td&gt;手动管理&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NSThread&lt;/td&gt;
&lt;td&gt;面向对象的线程封装&lt;/td&gt;
&lt;td&gt;OC/Swift&lt;/td&gt;
&lt;td&gt;手动管理&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GCD&lt;/td&gt;
&lt;td&gt;Grand Central Dispatch&lt;/td&gt;
&lt;td&gt;C/OC/Swift&lt;/td&gt;
&lt;td&gt;自动管理&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NSOperation&lt;/td&gt;
&lt;td&gt;基于GCD的面向对象封装&lt;/td&gt;
&lt;td&gt;OC/Swift&lt;/td&gt;
&lt;td&gt;自动管理&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="pthread"&gt;pthread&lt;/h2&gt;
&lt;p&gt;pthread是POSIX标准的多线程API，是最底层的多线程方案，使用C语言编写。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#import &amp;lt;pthread.h&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;threadFunction&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;param) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;NSLog&lt;/span&gt;(&lt;span style="color:#960050;background-color:#1e0010"&gt;@&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;pthread执行任务: %@&amp;#34;&lt;/span&gt;, [NSThread currentThread]);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; NULL;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)createPthread {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;pthread_t&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;thread&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;pthread_create&lt;/span&gt;(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;thread&lt;/span&gt;, NULL, threadFunction, NULL);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;特点&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;跨平台，可移植性强&lt;/li&gt;
&lt;li&gt;使用复杂，需要手动管理线程生命周期&lt;/li&gt;
&lt;li&gt;实际开发中很少直接使用&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="nsthread"&gt;NSThread&lt;/h2&gt;
&lt;p&gt;NSThread是苹果对pthread的面向对象封装，使用更加简单。&lt;/p&gt;
&lt;h3 id="创建线程的方式"&gt;创建线程的方式&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 方式1：实例方法创建，需要手动启动
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NSThread &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;thread&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [[NSThread alloc] initWithTarget:self
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; selector:&lt;span style="color:#66d9ef"&gt;@selector&lt;/span&gt;(doTask)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; object:nil];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;thread&lt;/span&gt;.name &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;@&amp;#34;MyThread&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[&lt;span style="color:#66d9ef"&gt;thread&lt;/span&gt; start];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 方式2：类方法创建，自动启动
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[NSThread detachNewThreadSelector:&lt;span style="color:#66d9ef"&gt;@selector&lt;/span&gt;(doTask)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; toTarget:self
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; withObject:nil];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 方式3：隐式创建
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[self performSelectorInBackground:&lt;span style="color:#66d9ef"&gt;@selector&lt;/span&gt;(doTask) withObject:nil];
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="常用方法"&gt;常用方法&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 获取当前线程
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NSThread &lt;span style="color:#f92672"&gt;*&lt;/span&gt;currentThread &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [NSThread currentThread];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 获取主线程
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NSThread &lt;span style="color:#f92672"&gt;*&lt;/span&gt;mainThread &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [NSThread mainThread];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 判断是否是主线程
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;BOOL&lt;/span&gt; isMain &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [NSThread isMainThread];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 线程休眠
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[NSThread sleepForTimeInterval:&lt;span style="color:#ae81ff"&gt;2.0&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:&lt;span style="color:#ae81ff"&gt;2.0&lt;/span&gt;]];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 退出当前线程
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[NSThread exit];
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="线程间通信"&gt;线程间通信&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objc" data-lang="objc"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 回到主线程执行
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[self performSelectorOnMainThread:&lt;span style="color:#66d9ef"&gt;@selector&lt;/span&gt;(updateUI)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; withObject:nil
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; waitUntilDone:NO];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 在指定线程执行
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;[self performSelector:&lt;span style="color:#66d9ef"&gt;@selector&lt;/span&gt;(doTask)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; onThread:&lt;span style="color:#66d9ef"&gt;thread&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; withObject:nil
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; waitUntilDone:NO];
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="gcdgrand-central-dispatch"&gt;GCD（Grand Central Dispatch）&lt;/h2&gt;
&lt;p&gt;GCD是苹果推出的多线程解决方案，基于C语言实现，自动管理线程的生命周期。GCD的核心概念是 &lt;strong&gt;队列（Queue）&lt;/strong&gt; 和&lt;strong&gt;任务（Task）&lt;/strong&gt;。&lt;/p&gt;</description></item><item><title>布局方法详解</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/%E5%B8%83%E5%B1%80%E6%96%B9%E6%B3%95%E8%AF%A6%E8%A7%A3/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/%E5%B8%83%E5%B1%80%E6%96%B9%E6%B3%95%E8%AF%A6%E8%A7%A3/</guid><description>&lt;p&gt;本文详细介绍 iOS 中三种布局方式（Frame、Auto Layout、UIStackView）的原理和对比，视图更新的三个阶段（约束、布局、绘制），UIView 与 CALayer 的关系和区别，以及 &lt;code&gt;updateConstraints&lt;/code&gt;、&lt;code&gt;layoutSubviews&lt;/code&gt;、&lt;code&gt;setNeedsLayout&lt;/code&gt;、&lt;code&gt;layoutIfNeeded&lt;/code&gt;、&lt;code&gt;setNeedsDisplay&lt;/code&gt; 等相关方法的作用、调用时机和区别。&lt;/p&gt;
&lt;h2 id="ios-布局方式"&gt;iOS 布局方式&lt;/h2&gt;
&lt;p&gt;iOS 提供了三种主要的布局方式，按出现时间排列：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;布局方式&lt;/th&gt;
&lt;th&gt;引入版本&lt;/th&gt;
&lt;th&gt;核心思想&lt;/th&gt;
&lt;th&gt;API&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Frame 布局&lt;/td&gt;
&lt;td&gt;iOS 2&lt;/td&gt;
&lt;td&gt;直接指定视图的位置和大小&lt;/td&gt;
&lt;td&gt;frame、bounds、center&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Auto Layout&lt;/td&gt;
&lt;td&gt;iOS 6&lt;/td&gt;
&lt;td&gt;通过约束描述视图间关系，系统自动计算 frame&lt;/td&gt;
&lt;td&gt;NSLayoutConstraint、Anchor API&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UIStackView&lt;/td&gt;
&lt;td&gt;iOS 9&lt;/td&gt;
&lt;td&gt;线性排列子视图，自动管理约束&lt;/td&gt;
&lt;td&gt;UIStackView&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="frame-布局"&gt;Frame 布局&lt;/h3&gt;
&lt;p&gt;直接通过设置 &lt;code&gt;frame&lt;/code&gt; 属性来确定视图的位置和大小，是最基础的布局方式。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; label = UILabel()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;label.frame = CGRect(x: &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;, y: &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;, width: &lt;span style="color:#ae81ff"&gt;200&lt;/span&gt;, height: &lt;span style="color:#ae81ff"&gt;44&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;view.addSubview(label)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;优点&lt;/strong&gt;：性能最好（无需约束求解），逻辑直观，完全可控。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;缺点&lt;/strong&gt;：需要手动计算所有数值，难以适配不同屏幕尺寸和动态内容，维护成本高。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;适用场景&lt;/strong&gt;：简单固定布局、性能敏感的场景（如 &lt;code&gt;UITableViewCell&lt;/code&gt; 内大量视图手动布局）、需要频繁更新 frame 的动画。&lt;/p&gt;
&lt;h3 id="auto-layout"&gt;Auto Layout&lt;/h3&gt;
&lt;p&gt;Auto Layout 是基于 &lt;strong&gt;约束（Constraint）&lt;/strong&gt; 的布局系统。开发者不直接设置 frame，而是描述视图之间的关系（如&amp;quot;A 的左边距 B 右边 16pt&amp;quot;），系统通过求解约束方程组自动计算出每个视图的 frame。&lt;/p&gt;</description></item><item><title>iOS中的生命周期</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F/</link><pubDate>Tue, 05 May 2026 00:41:41 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F/</guid><description>&lt;p&gt;iOS开发中，理解各种生命周期是非常重要的基础知识。本文将详细介绍应用生命周期、UIViewController生命周期、UIView生命周期，以及其他常见的生命周期。&lt;/p&gt;
&lt;h2 id="应用生命周期app-lifecycle"&gt;应用生命周期（App Lifecycle）&lt;/h2&gt;
&lt;h3 id="应用状态"&gt;应用状态&lt;/h3&gt;
&lt;p&gt;iOS应用有五种运行状态：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;状态&lt;/th&gt;
&lt;th&gt;描述&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Not Running&lt;/td&gt;
&lt;td&gt;应用未启动或已被系统终止&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Inactive&lt;/td&gt;
&lt;td&gt;应用在前台运行但未接收事件（如来电、锁屏时的过渡状态）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Active&lt;/td&gt;
&lt;td&gt;应用在前台运行并接收事件，这是应用的正常运行状态&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Background&lt;/td&gt;
&lt;td&gt;应用在后台执行代码，通常只有短暂的执行时间&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Suspended&lt;/td&gt;
&lt;td&gt;应用在后台但不执行代码，系统会在内存不足时自动终止该状态的应用&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="状态转换图"&gt;状态转换图&lt;/h3&gt;
&lt;pre class="mermaid"&gt;stateDiagram-v2
[*] --&gt; Not_Running
Not_Running --&gt; Inactive : 启动
Inactive --&gt; Active
Active --&gt; Background
Background --&gt; Inactive
Background --&gt; Suspended
Suspended --&gt; [*]
&lt;/pre&gt;
&lt;h3 id="uiapplicationdelegate-方法ios-12及之前"&gt;UIApplicationDelegate 方法（iOS 12及之前）&lt;/h3&gt;
&lt;p&gt;在iOS 12及之前的版本中，应用生命周期主要通过&lt;code&gt;UIApplicationDelegate&lt;/code&gt;协议来管理：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 应用启动完成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;application&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;_&lt;/span&gt; application: UIApplication,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -&amp;gt; Bool {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 初始化配置、第三方SDK等&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 应用即将进入非活动状态&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;applicationWillResignActive&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;_&lt;/span&gt; application: UIApplication) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 暂停正在进行的任务、禁用定时器&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 游戏应该在此暂停&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 应用已进入后台&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;applicationDidEnterBackground&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;_&lt;/span&gt; application: UIApplication) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 释放共享资源、保存用户数据&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 可以请求额外的后台执行时间&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 应用即将进入前台&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;applicationWillEnterForeground&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;_&lt;/span&gt; application: UIApplication) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 撤销进入后台时所做的更改&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 应用已变为活动状态&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;applicationDidBecomeActive&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;_&lt;/span&gt; application: UIApplication) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 重启被暂停的任务&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 如果应用之前在后台，可以刷新UI&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 应用即将终止&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;applicationWillTerminate&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;_&lt;/span&gt; application: UIApplication) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 保存数据、清理资源&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 注意：如果应用从Suspended状态被终止，此方法不会被调用&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="uiscenedelegate-方法ios-13"&gt;UISceneDelegate 方法（iOS 13+）&lt;/h3&gt;
&lt;p&gt;从iOS 13开始，Apple引入了Scene-based生命周期，支持多窗口场景。&lt;/p&gt;</description></item><item><title>类型擦除</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/%E7%B1%BB%E5%9E%8B%E6%93%A6%E9%99%A4/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/%E7%B1%BB%E5%9E%8B%E6%93%A6%E9%99%A4/</guid><description>&lt;p&gt;类型擦除（Type Erasure）是一种编程技术，用于在运行时隐藏具体的类型信息，使得不同类型可以通过统一的接口进行操作。在iOS开发中，Objective-C和Swift都有类型擦除的概念，但实现方式和应用场景有所不同。&lt;/p&gt;
&lt;h2 id="swift中的类型擦除"&gt;Swift中的类型擦除&lt;/h2&gt;
&lt;p&gt;Swift是一门强类型语言，类型信息在编译时被严格检查。但在某些场景下，我们需要隐藏具体类型信息，这时就需要使用类型擦除技术。&lt;/p&gt;
&lt;h3 id="存在类型与不透明类型"&gt;存在类型与不透明类型&lt;/h3&gt;
&lt;p&gt;在理解类型擦除之前，需要先理解 Swift 类型系统中两个关键概念：&lt;strong&gt;存在类型（Existential Type）&lt;/strong&gt; 和&lt;strong&gt;不透明类型（Opaque Type）&lt;/strong&gt;。它们是协议在类型层面的两种使用方式，也是理解 &lt;code&gt;any&lt;/code&gt; 和 &lt;code&gt;some&lt;/code&gt; 关键字的基础。&lt;/p&gt;
&lt;h4 id="存在类型existential-type"&gt;存在类型（Existential Type）&lt;/h4&gt;
&lt;p&gt;&amp;ldquo;存在类型&amp;quot;这个术语来自类型论中的存在量词（∃）。它表达的语义是：&lt;strong&gt;&amp;ldquo;存在某个类型 T 遵循了协议 P，但我不知道也不关心 T 具体是什么。&amp;rdquo;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;当你把一个协议当作类型来使用时（而非泛型约束），你就在使用存在类型：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;protocol&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Animal&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;makeSound&lt;/span&gt;() -&amp;gt; String
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Dog&lt;/span&gt;: Animal {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;makeSound&lt;/span&gt;() -&amp;gt; String { &lt;span style="color:#e6db74"&gt;&amp;#34;Woof!&amp;#34;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Cat&lt;/span&gt;: Animal {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;makeSound&lt;/span&gt;() -&amp;gt; String { &lt;span style="color:#e6db74"&gt;&amp;#34;Meow!&amp;#34;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// animals 数组中的每个元素都是存在类型&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 编译器不知道每个元素的具体类型，只知道&amp;#34;存在某个类型遵循了 Animal&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; animals: [any Animal] = [Dog(), Cat()]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;存在类型的核心特征：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;运行时多态&lt;/strong&gt;：具体类型在运行时才确定，同一个变量可以在不同时刻持有不同的具体类型&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;有性能开销&lt;/strong&gt;：Swift 通过存在容器（Existential Container）来存储值，方法调用需要通过见证表间接派发&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;类型信息被隐藏&lt;/strong&gt;：调用方只能通过协议接口与值交互，无法访问具体类型的特有成员&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在 Swift 5.6 之前，直接把协议写成类型（如 &lt;code&gt;let x: Animal&lt;/code&gt;）就是存在类型，但语法上没有任何标记。Swift 5.6 引入 &lt;code&gt;any&lt;/code&gt; 关键字使其变得显式，目的是提醒开发者这里存在运行时开销。Swift 5.7 起，对于带有关联类型的协议，必须使用 &lt;code&gt;any&lt;/code&gt; 才能作为存在类型。&lt;/p&gt;</description></item><item><title>计算机网络</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C/</link><pubDate>Sun, 03 May 2026 23:11:47 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-basics/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C/</guid><description>&lt;h2 id="网络分层模型"&gt;网络分层模型&lt;/h2&gt;
&lt;h3 id="osi七层模型"&gt;OSI七层模型&lt;/h3&gt;
&lt;p&gt;OSI（Open Systems Interconnection）是国际标准化组织提出的网络通信参考模型：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;层级&lt;/th&gt;
&lt;th&gt;名称&lt;/th&gt;
&lt;th&gt;功能&lt;/th&gt;
&lt;th&gt;协议/设备举例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;应用层&lt;/td&gt;
&lt;td&gt;为应用程序提供网络服务&lt;/td&gt;
&lt;td&gt;HTTP, FTP, DNS, SMTP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;表示层&lt;/td&gt;
&lt;td&gt;数据格式转换、加密/解密&lt;/td&gt;
&lt;td&gt;SSL/TLS, JPEG, ASCII&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;会话层&lt;/td&gt;
&lt;td&gt;建立、管理和终止会话&lt;/td&gt;
&lt;td&gt;RPC, SQL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;传输层&lt;/td&gt;
&lt;td&gt;端到端的可靠数据传输&lt;/td&gt;
&lt;td&gt;TCP, UDP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;网络层&lt;/td&gt;
&lt;td&gt;路由选择与IP寻址&lt;/td&gt;
&lt;td&gt;IP, ICMP, ARP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;数据链路层&lt;/td&gt;
&lt;td&gt;帧的封装与MAC寻址&lt;/td&gt;
&lt;td&gt;Ethernet, Wi-Fi&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;物理层&lt;/td&gt;
&lt;td&gt;比特流的物理传输&lt;/td&gt;
&lt;td&gt;光纤, 双绞线&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="tcpip四层模型"&gt;TCP/IP四层模型&lt;/h3&gt;
&lt;p&gt;实际工程中更常用的是TCP/IP四层模型，它将OSI的上三层合并为应用层，下两层合并为网络接口层：&lt;/p&gt;
&lt;pre class="mermaid"&gt;graph TB
subgraph "TCP/IP四层模型"
A["应用层&lt;br/&gt;HTTP, DNS, FTP, SMTP"]
B["传输层&lt;br/&gt;TCP, UDP"]
C["网络层&lt;br/&gt;IP, ICMP, ARP"]
D["网络接口层&lt;br/&gt;Ethernet, Wi-Fi"]
end
subgraph "OSI七层模型"
E["应用层"]
F["表示层"]
G["会话层"]
H["传输层"]
I["网络层"]
J["数据链路层"]
K["物理层"]
end
A --- E
A --- F
A --- G
B --- H
C --- I
D --- J
D --- K
&lt;/pre&gt;
&lt;h3 id="数据封装与解封装"&gt;数据封装与解封装&lt;/h3&gt;
&lt;p&gt;数据在发送方从上到下逐层封装，每一层都将上层传来的数据视为&lt;strong&gt;载荷（Payload）&lt;/strong&gt;，在其前面添加本层的头部信息（部分层还会添加尾部信息），然后交给下一层处理。接收方则从下到上逐层解封装，每一层剥离本层头部后将载荷交给上层。&lt;/p&gt;</description></item></channel></rss>