<?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/%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90/</link><description>Recent content in 源码分析 on Last Stand</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Wed, 08 Jul 2026 19:00:15 +0800</lastBuildDate><atom:link href="https://amatsuzero.github.io/LastStand/tags/%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90/index.xml" rel="self" type="application/rss+xml"/><item><title>Swift 面试：ARC 与内存管理源码解析</title><link>https://amatsuzero.github.io/LastStand/posts/swiftinterviewsourcecode/arc-memory-management/</link><pubDate>Tue, 16 Jun 2026 09:06:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/swiftinterviewsourcecode/arc-memory-management/</guid><description>&lt;h1 id="swift-面试arc-与内存管理源码解析"&gt;Swift 面试：ARC 与内存管理源码解析&lt;/h1&gt;
&lt;p&gt;Swift 面试里问 ARC，通常不是想听一句“自动引用计数”。真正要答清楚的是：&lt;strong&gt;对象头里有什么、strong / weak / unowned 到底差在哪里、编译器什么时候插入或消除 retain/release、为什么闭包会循环引用&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;这篇文章按面试题展开。先给可以直接回答的版本，再把结论落到 Swift 源码里的对象布局、引用计数状态机和 SIL ARC 优化。&lt;/p&gt;
&lt;h2 id="面试高频问题"&gt;面试高频问题&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Swift 的 ARC 和 Objective-C 的 ARC 有什么区别？&lt;/li&gt;
&lt;li&gt;Swift 对象的引用计数存在哪里？&lt;/li&gt;
&lt;li&gt;strong、weak、unowned 的底层差异是什么？&lt;/li&gt;
&lt;li&gt;为什么 weak 在对象释放后会自动变成 nil？&lt;/li&gt;
&lt;li&gt;为什么 unowned 访问已释放对象会崩溃？&lt;/li&gt;
&lt;li&gt;闭包为什么容易造成循环引用？&lt;/li&gt;
&lt;li&gt;编译器会如何优化 retain/release？&lt;/li&gt;
&lt;li&gt;值类型是否完全不参与 ARC？&lt;/li&gt;
&lt;li&gt;ARC 和 Copy-on-Write 有什么关系？&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="30-秒回答版"&gt;30 秒回答版&lt;/h2&gt;
&lt;p&gt;Swift ARC 是编译器和运行时共同完成的内存管理机制。&lt;/p&gt;
&lt;p&gt;编译器在 SIL 阶段根据所有权语义插入 &lt;code&gt;retain_value&lt;/code&gt;、&lt;code&gt;release_value&lt;/code&gt;、&lt;code&gt;strong_retain&lt;/code&gt;、&lt;code&gt;strong_release&lt;/code&gt; 等引用计数指令，并通过 ARC 优化尽量消除冗余 retain/release。运行时负责真正维护对象的引用计数。&lt;/p&gt;
&lt;p&gt;对原生 Swift 堆对象来说，对象头包含两部分：&lt;code&gt;metadata&lt;/code&gt; 和 &lt;code&gt;refCounts&lt;/code&gt;。源码里 &lt;code&gt;HeapObject&lt;/code&gt; 的注释明确说 &lt;code&gt;metadata&lt;/code&gt; 总是指向一个有效的 metadata 对象，&lt;code&gt;refCounts&lt;/code&gt; 是 Swift heap object header 的非 Objective-C 成员。&lt;/p&gt;</description></item><item><title>objc4 类加载、read_images 与类实现化</title><link>https://amatsuzero.github.io/LastStand/posts/ocsourcecodeanalysis/class-realization-explained/</link><pubDate>Mon, 01 Jun 2026 19:50:12 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/ocsourcecodeanalysis/class-realization-explained/</guid><description>&lt;h1 id="objc4-类加载read_images-与类实现化"&gt;objc4 类加载、read_images 与类实现化&lt;/h1&gt;
&lt;p&gt;本文解释 Objective-C runtime 从 dyld 通知镜像映射，到读取类、处理 future class、realize class、methodize class、附着 category 的主干流程。 重点源码来自 &lt;code&gt;runtime/objc-runtime-new.mm&lt;/code&gt;、&lt;code&gt;objc-runtime-new.h&lt;/code&gt;、&lt;code&gt;objc-os.mm&lt;/code&gt;、&lt;code&gt;objc-class.mm&lt;/code&gt; 及相关测试。&lt;/p&gt;
&lt;p&gt;&lt;a href="#purpose"&gt;作用&lt;/a&gt; &lt;a href="#structures"&gt;核心结构&lt;/a&gt; &lt;a href="#flow"&gt;关键流程&lt;/a&gt; &lt;a href="#tests"&gt;测试视角&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="一这条链路的作用"&gt;一、这条链路的作用&lt;/h2&gt;
&lt;h3 id="把-mach-o-中的静态元数据变成运行时可用的类"&gt;把 Mach-O 中的静态元数据变成运行时可用的类&lt;/h3&gt;
&lt;p&gt;编译器把类、元类、方法列表、协议列表、属性列表和 ivar 布局写入 Mach-O 的 Objective-C sections。 这些数据起初主要是只读的 &lt;code&gt;class_ro_t&lt;/code&gt;。runtime 加载镜像时要登记类名、修正 selector/protocol/class 引用，并在必要时分配可写的 &lt;code&gt;class_rw_t&lt;/code&gt;。&lt;/p&gt;
&lt;h3 id="延迟成本同时保证消息发送能看到正确结构"&gt;延迟成本，同时保证消息发送能看到正确结构&lt;/h3&gt;
&lt;p&gt;大量类可以保持未 realized 状态，直到非懒加载、&lt;code&gt;+load&lt;/code&gt;、消息发送、Swift 桥接或显式 API 需要它们。 realize 时才连接父类和元类、修正 ivar 偏移、初始化 cache、复制运行时标志，并把方法列表整理成可查找的形态。&lt;/p&gt;
&lt;p&gt;简化理解：&lt;code&gt;read_images&lt;/code&gt; 是“发现并登记”；&lt;code&gt;readClass&lt;/code&gt; 是“读一个类声明并处理 future/remap”；&lt;code&gt;realizeClassWithoutSwift&lt;/code&gt; 是“把类接入运行时继承图”；&lt;code&gt;methodizeClass&lt;/code&gt; 是“准备方法/协议/属性并合并 category”。&lt;/p&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;关键字段&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;objc_class&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;superclass&lt;/code&gt;、&lt;code&gt;cache&lt;/code&gt;、&lt;code&gt;bits&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;类对象本体。&lt;code&gt;bits&lt;/code&gt; 初始可指向 &lt;code&gt;class_ro_t&lt;/code&gt;，realize 后指向 &lt;code&gt;class_rw_t&lt;/code&gt; 并夹带 fast flags。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;class_ro_t&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;flags&lt;/code&gt;、&lt;code&gt;instanceStart&lt;/code&gt;、&lt;code&gt;instanceSize&lt;/code&gt;、&lt;code&gt;name&lt;/code&gt;、&lt;code&gt;baseMethods&lt;/code&gt;、&lt;code&gt;ivars&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;编译期只读描述。包含类名、方法、协议、属性、ivar 布局和 root/meta/future/realized 等 ABI 标志。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;class_rw_t&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;flags&lt;/code&gt;、&lt;code&gt;ro_or_rw_ext&lt;/code&gt;、&lt;code&gt;firstSubclass&lt;/code&gt;、&lt;code&gt;nextSiblingClass&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;运行时可写状态。保存 realized/initialized/constructing 等状态，并把类接入子类链。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;class_rw_ext_t&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ro&lt;/code&gt;、&lt;code&gt;methods&lt;/code&gt;、&lt;code&gt;properties&lt;/code&gt;、&lt;code&gt;protocols&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;当类需要扩展列表时分配。category 附着后，方法/属性/协议列表通常进入这里。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;method_list_t&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;entsizeAndFlags&lt;/code&gt;、&lt;code&gt;count&lt;/code&gt;、方法条目&lt;/td&gt;
&lt;td&gt;方法列表。加载时会 uniquing selector，必要时排序并标记 fixed-up。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;category_t&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;cls&lt;/code&gt;、&lt;code&gt;instanceMethods&lt;/code&gt;、&lt;code&gt;classMethods&lt;/code&gt;、&lt;code&gt;protocols&lt;/code&gt;、&lt;code&gt;instanceProperties&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;分类元数据。目标类已 realized 时立即附着，否则暂存到 unattached categories。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;header_info&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;classlist&lt;/code&gt;、&lt;code&gt;nlclslist&lt;/code&gt;、&lt;code&gt;catlist&lt;/code&gt;、&lt;code&gt;selrefs&lt;/code&gt;、&lt;code&gt;protocolrefs&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;一个 Mach-O 镜像的 ObjC 元数据索引。&lt;code&gt;objc-os.mm&lt;/code&gt; 中 &lt;code&gt;addHeader&lt;/code&gt; 负责创建或取出它。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="类数据从-ro-切换到-rw"&gt;类数据从 ro 切换到 rw&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-cpp" data-lang="cpp"&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;objc_class&lt;/span&gt; &lt;span style="color:#f92672"&gt;:&lt;/span&gt; objc_object {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Class superclass;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; cache_t cache;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; class_data_bits_t bits; &lt;span style="color:#75715e"&gt;// 未实现时指向 class_ro_t，实现后指向 class_rw_t
&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;class_rw_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;uint32_t&lt;/span&gt; flags; &lt;span style="color:#75715e"&gt;// RW_REALIZED、RW_FUTURE、RW_INITIALIZED 等
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; explicit_atomic&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;uintptr_t&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; ro_or_rw_ext;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Class firstSubclass;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Class nextSiblingClass;
&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;class_data_bits_t::safe_ro()&lt;/code&gt; 允许在并发 realize 场景下安全取出 ro。 &lt;code&gt;setData()&lt;/code&gt; 则在 realization 或构造阶段把 &lt;code&gt;objc_class::bits&lt;/code&gt; 改成 rw 指针，并设置 &lt;code&gt;FAST_IS_RW_POINTER&lt;/code&gt;。&lt;/p&gt;</description></item><item><title>AFNetworking 源码导读</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/afnetworking%E6%BA%90%E7%A0%81%E5%AF%BC%E8%AF%BB/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/afnetworking%E6%BA%90%E7%A0%81%E5%AF%BC%E8%AF%BB/</guid><description>&lt;blockquote&gt;
&lt;p&gt;本文基于 &lt;strong&gt;AFNetworking 4.0.1&lt;/strong&gt;（2020 年发布，仓库最后一次迭代）源码进行分析。AFNetworking 虽然已进入&amp;quot;稳定休眠&amp;quot;状态，但它作为 iOS 网络层的教科书级实现，其 &lt;code&gt;NSURLSession&lt;/code&gt; 封装、HTTPS 校验、Multipart 流式上传、Method Swizzling 等设计思路至今仍值得每一位 iOS 工程师学习。源码仓库：&lt;a href="https://github.com/AFNetworking/AFNetworking"&gt;AFNetworking/AFNetworking&lt;/a&gt;。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一整体架构"&gt;一、整体架构&lt;/h2&gt;
&lt;p&gt;AFNetworking 的整个库只有 &lt;strong&gt;7 个核心类&lt;/strong&gt;，按职责划分为&amp;quot;核心会话&amp;quot;、&amp;ldquo;序列化&amp;rdquo;、&amp;ldquo;安全&amp;rdquo;、&amp;ldquo;可达性&amp;rdquo;、&amp;ldquo;UIKit 扩展&amp;quot;五个子模块（对应 CocoaPods Subspec 拆分）：&lt;/p&gt;
&lt;pre class="mermaid"&gt;graph TB
subgraph "核心会话层 (NSURLSession 封装)"
A["AFURLSessionManager&lt;br/&gt;NSURLSession 代理总线"]
B["AFHTTPSessionManager&lt;br/&gt;HTTP 便利方法 GET/POST/..."]
C["AFURLSessionManagerTaskDelegate&lt;br/&gt;每个 Task 的代理持有者"]
end
subgraph "序列化层 (Serialization)"
D["AFHTTPRequestSerializer&lt;br/&gt;URL 编码 / 头部 / User-Agent"]
E["AFJSONRequestSerializer&lt;br/&gt;AFPropertyListRequestSerializer"]
F["AFStreamingMultipartFormData&lt;br/&gt;AFMultipartBodyStream (流式上传)"]
G["AFHTTPResponseSerializer&lt;br/&gt;+ JSON/XML/Image/PropertyList"]
end
subgraph "安全层 (Security)"
H["AFSecurityPolicy&lt;br/&gt;SSL Pinning (None/Certificate/PublicKey)"]
end
subgraph "可达性层 (Reachability)"
I["AFNetworkReachabilityManager&lt;br/&gt;基于 SCNetworkReachability"]
end
subgraph "UI 扩展 (UIKit+AFNetworking)"
J["UIImageView+AFNetworking&lt;br/&gt;UIButton+AFNetworking&lt;br/&gt;UIActivityIndicatorView+AFNetworking ..."]
end
B --&gt; A
A --&gt; C
A --&gt; D
A --&gt; G
A --&gt; H
A --&gt; I
D --&gt; E
D --&gt; F
J --&gt; B
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;源码目录一览&lt;/strong&gt;（&lt;code&gt;AFNetworking 4.0.1&lt;/code&gt;）：&lt;/p&gt;</description></item><item><title>Swift 面试：泛型、协议与派发源码解析</title><link>https://amatsuzero.github.io/LastStand/posts/swiftinterviewsourcecode/generics-protocol-dispatch/</link><pubDate>Tue, 16 Jun 2026 09:06:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/swiftinterviewsourcecode/generics-protocol-dispatch/</guid><description>&lt;h1 id="swift-面试泛型协议与派发源码解析"&gt;Swift 面试：泛型、协议与派发源码解析&lt;/h1&gt;
&lt;p&gt;Swift 面试里，泛型和协议经常不是单独问语法，而是连着问：&lt;strong&gt;Swift 中函数派发机制有哪几种？泛型是编译期还是运行期机制？协议调用为什么可能慢？&lt;code&gt;some&lt;/code&gt; 和 &lt;code&gt;any&lt;/code&gt; 为什么性能不同？Protocol Witness Table 到底是什么？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这篇文章按面试题展开，把答案落到 Swift 编译器里的 Generic Signature、Generic Specializer、SIL 调用指令、Protocol Witness Table、class vtable 和 Devirtualize 优化。&lt;/p&gt;
&lt;h2 id="面试高频问题"&gt;面试高频问题&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Swift 中函数派发机制有哪几种？&lt;/li&gt;
&lt;li&gt;直接派发、class vtable 派发、witness table 派发、Objective-C 消息派发分别适用于什么场景？&lt;/li&gt;
&lt;li&gt;&lt;code&gt;function_ref&lt;/code&gt;、&lt;code&gt;class_method&lt;/code&gt;、&lt;code&gt;witness_method&lt;/code&gt;、&lt;code&gt;objc_method&lt;/code&gt; 在 SIL 里分别代表什么？&lt;/li&gt;
&lt;li&gt;如何用 &lt;code&gt;swiftc -emit-silgen&lt;/code&gt; / &lt;code&gt;swiftc -emit-sil -O&lt;/code&gt; 观察派发指令？&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dynamic&lt;/code&gt; / &lt;code&gt;@objc dynamic&lt;/code&gt; 会怎样影响派发？&lt;/li&gt;
&lt;li&gt;如何用代码对比泛型、&lt;code&gt;some&lt;/code&gt;、&lt;code&gt;any&lt;/code&gt; 的派发和性能差异？&lt;/li&gt;
&lt;li&gt;Swift 泛型是运行时泛型还是编译期泛型？&lt;/li&gt;
&lt;li&gt;Generic Signature 是什么？它保存哪些信息？&lt;/li&gt;
&lt;li&gt;泛型特化为什么能提升性能？&lt;/li&gt;
&lt;li&gt;Protocol Witness Table 是什么？&lt;/li&gt;
&lt;li&gt;协议方法调用什么时候是静态派发，什么时候是动态派发？&lt;/li&gt;
&lt;li&gt;&lt;code&gt;some Protocol&lt;/code&gt; 和 &lt;code&gt;any Protocol&lt;/code&gt; 的本质区别是什么？&lt;/li&gt;
&lt;li&gt;&lt;code&gt;final&lt;/code&gt;、&lt;code&gt;private&lt;/code&gt;、具体类型为什么有利于优化？&lt;/li&gt;
&lt;li&gt;协议扩展里的方法一定是动态派发吗？&lt;/li&gt;
&lt;li&gt;&lt;code&gt;class_method&lt;/code&gt; 和 &lt;code&gt;witness_method&lt;/code&gt; 有什么区别？&lt;/li&gt;
&lt;li&gt;面试里如何解释“Swift 既强调协议，又强调性能”？&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="30-秒回答版"&gt;30 秒回答版&lt;/h2&gt;
&lt;p&gt;Swift 函数派发面试不要只答“静态派发和动态派发”。更完整的分类是：&lt;strong&gt;直接派发&lt;/strong&gt;、&lt;strong&gt;class vtable 派发&lt;/strong&gt;、&lt;strong&gt;protocol witness table 派发&lt;/strong&gt;、&lt;strong&gt;Objective-C 消息派发&lt;/strong&gt;，再补充优化器可能把动态调用去虚拟化成直接调用。&lt;/p&gt;</description></item><item><title>Objective-C 消息发送 objc_msgSend 与慢速查找入口</title><link>https://amatsuzero.github.io/LastStand/posts/ocsourcecodeanalysis/message-send-explained/</link><pubDate>Mon, 01 Jun 2026 19:50:12 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/ocsourcecodeanalysis/message-send-explained/</guid><description>&lt;p&gt;objc4 runtime dispatch&lt;/p&gt;
&lt;h1 id="objective-c-消息发送objc_msgsend-与慢速查找入口"&gt;Objective-C 消息发送：objc_msgSend 与慢速查找入口&lt;/h1&gt;
&lt;p&gt;Objective-C 的方法调用本质上是一次以 &lt;code&gt;receiver&lt;/code&gt; 和 &lt;code&gt;SEL&lt;/code&gt; 为键的动态派发。 在 arm64 上，&lt;code&gt;objc_msgSend&lt;/code&gt; 先用少量汇编完成 nil/tagged pointer 判断和方法缓存查找； 只有缓存未命中时，才进入 C++ 慢路径 &lt;code&gt;lookUpImpOrForward&lt;/code&gt;，沿类层级查找、触发动态解析、填充缓存或进入消息转发。&lt;/p&gt;
&lt;p&gt;入口：runtime/Messengers.subproj/objc-msg-arm64.s 慢路径：runtime/objc-runtime-new.mm 缓存：runtime/objc-cache.mm 测试：test/msgSend.m&lt;/p&gt;
&lt;h2 id="目录"&gt;目录&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="#purpose"&gt;作用&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#principle"&gt;实现原理总览&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#structures"&gt;核心结构与约定&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#fast-path"&gt;快速路径&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#slow-path"&gt;慢速查找入口&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#forwarding"&gt;消息转发&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#tests"&gt;测试观察点&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;a id="purpose"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="作用"&gt;作用&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;objc_msgSend(id self, SEL _cmd, ...)&lt;/code&gt; 是 Objective-C 实例方法和类方法调用的公共派发入口。 编译器把 &lt;code&gt;[obj method:arg]&lt;/code&gt; 形式的调用降低为对 &lt;code&gt;objc_msgSend&lt;/code&gt; 的调用；真正执行哪个 &lt;code&gt;IMP&lt;/code&gt; 由运行时根据接收者的实际类、选择子和当前方法缓存决定。&lt;/p&gt;
&lt;h3 id="动态派发"&gt;动态派发&lt;/h3&gt;
&lt;p&gt;同一个 &lt;code&gt;SEL&lt;/code&gt; 可以在不同类上命中不同 &lt;code&gt;IMP&lt;/code&gt;，体现多态。&lt;/p&gt;
&lt;h3 id="缓存加速"&gt;缓存加速&lt;/h3&gt;
&lt;p&gt;大多数热路径只扫描类的 &lt;code&gt;cache_t&lt;/code&gt;，命中后直接尾调用 &lt;code&gt;IMP&lt;/code&gt;。&lt;/p&gt;
&lt;h3 id="语义兼容"&gt;语义兼容&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;nil&lt;/code&gt; 接收者返回零值；tagged pointer 通过标签映射到伪类继续派发。&lt;/p&gt;
&lt;h3 id="扩展入口"&gt;扩展入口&lt;/h3&gt;
&lt;p&gt;未找到实现时支持 &lt;code&gt;+resolve...&lt;/code&gt; 和完整的 forwarding 机制。&lt;/p&gt;</description></item><item><title>Alamofire源码导读</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/alamofire%E6%BA%90%E7%A0%81%E5%AF%BC%E8%AF%BB/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/alamofire%E6%BA%90%E7%A0%81%E5%AF%BC%E8%AF%BB/</guid><description>&lt;p&gt;Alamofire 是 Swift 社区最广泛使用的 HTTP 网络库，由 Alamofire Software Foundation 维护，在 GitHub 已收获 42k+ star。它在 &lt;code&gt;URLSession&lt;/code&gt; 之上构建了一整套链式 API、拦截器、认证、证书校验、重试与响应序列化等能力。本文基于最新版本 &lt;strong&gt;v5.11.2&lt;/strong&gt;（2026 年 4 月发布）源码进行分析，覆盖 Swift 6 严格并发、async/await、WebSocket、OfflineRetrier 等最新特性。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="一整体架构"&gt;一、整体架构&lt;/h2&gt;
&lt;p&gt;Alamofire 采用&lt;strong&gt;中央调度 + 状态机 + 协议导向&lt;/strong&gt;的设计，核心角色分工清晰：&lt;/p&gt;
&lt;pre class="mermaid"&gt;graph TB
subgraph "入口层"
AF["AF&lt;br/&gt;(Session.default)"]
end
subgraph "调度层"
S["Session&lt;br/&gt;统一调度器"]
SD["SessionDelegate&lt;br/&gt;URLSession 桥接"]
end
subgraph "请求层"
R["Request (基类)&lt;br/&gt;状态机 + 生命周期"]
DR["DataRequest"]
DLR["DownloadRequest"]
UR["UploadRequest"]
DSR["DataStreamRequest"]
WSR["WebSocketRequest"]
end
subgraph "拦截层"
RA["RequestAdapter&lt;br/&gt;请求改写"]
RR["RequestRetrier&lt;br/&gt;失败重试"]
RI["RequestInterceptor&lt;br/&gt;= Adapter + Retrier"]
end
subgraph "服务层"
RS["ResponseSerializer&lt;br/&gt;响应序列化"]
STE["ServerTrustEvaluating&lt;br/&gt;证书/公钥校验"]
EM["EventMonitor&lt;br/&gt;事件监控"]
MP["MultipartFormData&lt;br/&gt;表单编码"]
end
subgraph "系统层"
US["URLSession / URLSessionTask"]
end
AF --&gt; S
S --&gt; SD
S --&gt;|创建| R
R --&gt; DR &amp; DLR &amp; UR &amp; DSR &amp; WSR
S -.使用.-&gt; RI
RI -.= .-&gt; RA &amp; RR
R -.序列化.-&gt; RS
SD -.校验.-&gt; STE
S -.通知.-&gt; EM
UR -.构建.-&gt; MP
SD &lt;--&gt;|delegate| US
R --&gt;|执行| US
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;源码目录（&lt;code&gt;Source/&lt;/code&gt;，总计约 17000 行纯 Swift 代码）：&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>Swift 面试：值语义、COW 与集合源码解析</title><link>https://amatsuzero.github.io/LastStand/posts/swiftinterviewsourcecode/value-semantics-cow-collections/</link><pubDate>Tue, 16 Jun 2026 09:06:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/swiftinterviewsourcecode/value-semantics-cow-collections/</guid><description>&lt;h1 id="swift-面试值语义cow-与集合源码解析"&gt;Swift 面试：值语义、COW 与集合源码解析&lt;/h1&gt;
&lt;p&gt;Swift 的 &lt;code&gt;Array&lt;/code&gt;、&lt;code&gt;String&lt;/code&gt;、&lt;code&gt;Dictionary&lt;/code&gt; 都表现为值类型，但它们不可能每次赋值都完整复制底层存储。面试官问值语义和 COW，真正想看的是你能不能说清楚：&lt;strong&gt;值语义是语言语义，COW 是性能实现；集合表面是 struct，底层经常共享引用存储；写入前靠唯一性检查决定是否复制。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这篇文章从面试题出发，把结论落到 Swift 标准库源码里的 Array buffer、String guts、Dictionary storage 和 &lt;code&gt;isKnownUniquelyReferenced&lt;/code&gt;。&lt;/p&gt;
&lt;h2 id="面试高频问题"&gt;面试高频问题&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Swift 的 struct 为什么常说是值语义？&lt;/li&gt;
&lt;li&gt;Array 赋值时一定会复制底层元素吗？&lt;/li&gt;
&lt;li&gt;Copy-on-Write 的触发条件是什么？&lt;/li&gt;
&lt;li&gt;&lt;code&gt;isKnownUniquelyReferenced&lt;/code&gt; 检查的到底是什么？&lt;/li&gt;
&lt;li&gt;Array、ContiguousArray、ArrayBuffer、Storage 是什么关系？&lt;/li&gt;
&lt;li&gt;String 为什么不能用整数下标随机访问？&lt;/li&gt;
&lt;li&gt;String.Index 为什么不是一个简单的 Int？&lt;/li&gt;
&lt;li&gt;Dictionary 也是 COW 吗？&lt;/li&gt;
&lt;li&gt;ArraySlice 为什么可能持有原数组存储？&lt;/li&gt;
&lt;li&gt;值类型里包含 class 引用，还算值语义吗？&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="30-秒回答版"&gt;30 秒回答版&lt;/h2&gt;
&lt;p&gt;Swift 的值语义是说：从语言使用者角度看，赋值、传参、修改不会意外影响另一个值。但这不等于底层每次都立即复制。&lt;/p&gt;
&lt;p&gt;标准库集合通常用 Copy-on-Write 实现：多个值可以共享同一份堆上 buffer；只有当某个值要写入时，才检查底层 buffer 是否唯一引用。如果唯一，就原地修改；如果不唯一，就复制一份新 buffer 再修改。&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-text" data-lang="text"&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;COW：实现上先共享，写入前再判断是否复制
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ARC：维护底层 buffer 的引用计数
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;isUnique：让 COW 判断能否原地修改
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;面试可以这样回答：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Swift 的 Array 是 struct，但它内部持有引用语义的 storage。赋值时通常只复制结构体里的引用；真正写入时通过唯一性检查决定是否复制底层 storage。这让 Array 同时具备值语义和接近引用共享的性能。&lt;/p&gt;</description></item><item><title>objc4 方法缓存 cache_t / bucket_t 技术讲解</title><link>https://amatsuzero.github.io/LastStand/posts/ocsourcecodeanalysis/method-cache-explained/</link><pubDate>Mon, 01 Jun 2026 19:50:12 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/ocsourcecodeanalysis/method-cache-explained/</guid><description>&lt;h1 id="objc4-方法缓存-cache_t--bucket_t-技术讲解"&gt;objc4 方法缓存 cache_t / bucket_t 技术讲解&lt;/h1&gt;
&lt;p&gt;本文基于当前仓库中的 &lt;code&gt;runtime/objc-cache.mm&lt;/code&gt;、 &lt;code&gt;runtime/objc-runtime-new.h&lt;/code&gt;、&lt;code&gt;runtime/objc-runtime-new.mm&lt;/code&gt; 以及 cache flush 相关测试，说明 Objective-C runtime 如何把一次慢速方法查找变成后续的快速 &lt;code&gt;objc_msgSend&lt;/code&gt; cache hit。&lt;/p&gt;
&lt;h2 id="一方法缓存的作用"&gt;一、方法缓存的作用&lt;/h2&gt;
&lt;p&gt;Objective-C 消息发送以 &lt;code&gt;(Class, SEL)&lt;/code&gt; 为核心输入。完整方法查找需要处理类实现、父类链、 动态方法解析、转发和分类变更等逻辑，代价高于一次普通函数调用。&lt;code&gt;cache_t&lt;/code&gt; 是挂在每个 &lt;code&gt;objc_class&lt;/code&gt; 上的 IMP cache，用 &lt;code&gt;SEL&lt;/code&gt; 作为 key，缓存最终应该调用的 &lt;code&gt;IMP&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;加速热路径&lt;/strong&gt;命中时 &lt;code&gt;objc_msgSend&lt;/code&gt; 不进入 runtime 慢路径，直接由 bucket 中的 IMP 跳转。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;缓存继承结果&lt;/strong&gt;子类未实现某 selector 时，也可以把父类找到的 IMP 缓存在子类 cache 中。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;支持动态变更&lt;/strong&gt;分类加载、添加方法、交换实现等操作会触发 cache flush，避免继续调用旧 IMP。&lt;/p&gt;
&lt;p&gt;cache 不是方法列表本身，也不是权威数据源。它是一个可丢弃、可重建的性能结构；扩容时甚至不会搬迁旧条目， 而是让后续消息重新填充热点 selector。&lt;/p&gt;
&lt;h2 id="二核心结构"&gt;二、核心结构&lt;/h2&gt;
&lt;h3 id="bucket_t一个-selector-到-imp-的槽位"&gt;&lt;code&gt;bucket_t&lt;/code&gt;：一个 selector 到 IMP 的槽位&lt;/h3&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;字段&lt;/td&gt;
&lt;td&gt;&lt;code&gt;_sel&lt;/code&gt; 保存 selector，&lt;code&gt;_imp&lt;/code&gt; 保存编码后的 IMP。arm64 上 IMP 在前，其他架构通常 SEL 在前，以贴合汇编 fast path 和指针认证需求。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sel()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;以 relaxed atomic 读取 selector。空槽的 selector 为 0。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;imp(base, cls)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;读取并解码 IMP。arm64e 可使用 ptrauth，部分配置使用 class 指针 XOR，未编码配置则直接返回。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;set&amp;lt;Atomic, Encoded&amp;gt;()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;写入一个 bucket。写入顺序被精心安排，保证无锁读取者不会看到“新 SEL + 旧 IMP”的错误组合。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="cache_t每个类上的哈希表"&gt;&lt;code&gt;cache_t&lt;/code&gt;：每个类上的哈希表&lt;/h3&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;&lt;code&gt;_bucketsAndMaybeMask&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;保存 buckets 指针，有些 64 位配置还把 mask 打包进高位；preoptimized cache 也用低位 marker 复用这个字段。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;_mask&lt;/code&gt; / 内联 mask&lt;/td&gt;
&lt;td&gt;bucket 数量始终为 2 的幂，&lt;code&gt;mask = capacity - 1&lt;/code&gt;，哈希后用按位与得到起始槽。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;_occupied&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;已占用动态 bucket 数。插入成功后递增；换表时清零。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;_flags&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;保存若干快速路径标记，例如 metaclass、C++ ctor/dtor、默认 alloc 或 RR 等，具体位定义在 &lt;code&gt;objc-runtime-new.h&lt;/code&gt;。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;关键方法&lt;/td&gt;
&lt;td&gt;&lt;code&gt;insert&lt;/code&gt;、&lt;code&gt;eraseNolock&lt;/code&gt;、&lt;code&gt;destroy&lt;/code&gt;、&lt;code&gt;copyCacheNolock&lt;/code&gt;、&lt;code&gt;maybeConvertToPreoptimized&lt;/code&gt;、&lt;code&gt;preoptFallbackClass&lt;/code&gt;。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="preopt_cache_tdyld-shared-cache-预构建的常量-cache"&gt;&lt;code&gt;preopt_cache_t&lt;/code&gt;：dyld shared cache 预构建的常量 cache&lt;/h3&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;&lt;code&gt;fallback_class_offset&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;预优化查找未覆盖时继续查找的类，相对当前 class 地址保存。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;shift&lt;/code&gt; / &lt;code&gt;mask&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;用于计算预优化 entries 下标。&lt;code&gt;capacity()&lt;/code&gt; 返回 &lt;code&gt;mask + 1&lt;/code&gt;。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;occupied&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;预优化 cache 中的有效条目数量。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;has_inlines&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;标记是否存在内联 selector；方法列表变更时需要更谨慎地禁用这类 cache。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;entries[]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;每项保存 selector offset 和 IMP offset，而不是直接保存完整指针。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="三实现原理"&gt;三、实现原理&lt;/h2&gt;
&lt;p&gt;动态 cache 是一个开放寻址哈希表。&lt;code&gt;cache_hash(sel, mask)&lt;/code&gt; 用 selector 地址和 mask 得到起始槽； 冲突时调用 &lt;code&gt;cache_next&lt;/code&gt; 继续探测。不同架构的探测方向不同：部分架构递增并使用 end marker， arm64 递减并通过 mask 回绕。&lt;/p&gt;</description></item><item><title>IGListKit源码导读</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/iglistkit%E6%BA%90%E7%A0%81%E5%AF%BC%E8%AF%BB/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/iglistkit%E6%BA%90%E7%A0%81%E5%AF%BC%E8%AF%BB/</guid><description>&lt;p&gt;IGListKit 是 Instagram（Meta）开源的一款数据驱动的 UICollectionView 框架，旨在构建快速、灵活的列表。它的核心思想是将每个数据对象映射为独立的 Section Controller，通过高效的 O(n) Diff 算法自动计算数据变化并应用最小化更新，避免手动调用 &lt;code&gt;performBatchUpdates&lt;/code&gt; 或 &lt;code&gt;reloadData&lt;/code&gt;。本文基于 v5.2.0 源码（2026年2月发布）进行分析。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="一整体架构"&gt;一、整体架构&lt;/h2&gt;
&lt;p&gt;IGListKit 采用分层架构，核心由三大模块构成：&lt;/p&gt;
&lt;pre class="mermaid"&gt;graph TB
subgraph "使用层"
A["UIViewController"]
end
subgraph "适配层"
B["IGListAdapter"]
C["IGListAdapterDataSource"]
end
subgraph "控制层"
D["IGListSectionController"]
E["IGListBindingSectionController"]
end
subgraph "更新层"
F["IGListAdapterUpdater"]
G["IGListUpdateCoalescer"]
H["IGListUpdateTransaction"]
end
subgraph "Diff层 (IGListDiffKit)"
I["IGListDiff&lt;br/&gt;Paul Heckel算法"]
J["IGListDiffable协议"]
end
subgraph "视图层"
K["UICollectionView"]
end
A --&gt; B
B --&gt; C
B --&gt; D
D --&gt; E
B --&gt; F
F --&gt; G
F --&gt; H
H --&gt; I
I --&gt; J
B --&gt; K
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;源码目录结构：&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>Swift 面试：并发、async/await 与 Actor 源码解析</title><link>https://amatsuzero.github.io/LastStand/posts/swiftinterviewsourcecode/concurrency-actor-async/</link><pubDate>Tue, 16 Jun 2026 09:06:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/swiftinterviewsourcecode/concurrency-actor-async/</guid><description>&lt;h1 id="swift-面试并发asyncawait-与-actor-源码解析"&gt;Swift 面试：并发、async/await 与 Actor 源码解析&lt;/h1&gt;
&lt;p&gt;Swift Concurrency 面试经常从 &lt;code&gt;async/await&lt;/code&gt; 问起，但真正的重点是：&lt;strong&gt;Task 是结构化并发的执行单元，await 是显式暂停点，Actor 通过隔离和串行执行器保护状态，Sendable 则约束跨并发边界传递的数据。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这篇文章按面试题展开，把结论落到 Swift 标准库和编译器源码里的 Actor、GlobalActor、MainActor、AsyncLet、TaskGroup、Sendable 和 ActorIsolation。&lt;/p&gt;
&lt;h2 id="面试高频问题"&gt;面试高频问题&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;async/await 和 GCD 的关系是什么？&lt;/li&gt;
&lt;li&gt;&lt;code&gt;await&lt;/code&gt; 到底表示线程阻塞还是任务暂停？&lt;/li&gt;
&lt;li&gt;Task、async let、TaskGroup 有什么区别？&lt;/li&gt;
&lt;li&gt;Actor 如何保证数据隔离？&lt;/li&gt;
&lt;li&gt;MainActor 是什么，为什么 UI 更新要回到 MainActor？&lt;/li&gt;
&lt;li&gt;GlobalActor 和普通 Actor 有什么区别？&lt;/li&gt;
&lt;li&gt;Sendable 解决什么问题？&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Task.detached&lt;/code&gt; 为什么要慎用？&lt;/li&gt;
&lt;li&gt;Actor 之间调用为什么需要 &lt;code&gt;await&lt;/code&gt;？&lt;/li&gt;
&lt;li&gt;Swift Concurrency 是编译器机制还是运行时机制？&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="30-秒回答版"&gt;30 秒回答版&lt;/h2&gt;
&lt;p&gt;Swift Concurrency 是编译器、标准库和运行时共同完成的并发模型。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;async/await&lt;/code&gt; 不是对 GCD 的简单语法糖。&lt;code&gt;await&lt;/code&gt; 表示当前异步任务可能在这里暂停，把执行权交还给调度器；等异步结果可用时，再从 continuation 恢复。它不应该理解成“阻塞当前线程等待”。&lt;/p&gt;
&lt;p&gt;Actor 是一种受隔离保护的引用类型。Actor 内部可变状态只能在 actor 隔离域内访问；跨 actor 访问必须异步，编译器会插入隔离检查。运行时通过 executor 保证同一 actor 的隔离状态不会被多个任务同时进入。&lt;/p&gt;</description></item><item><title>Objective-C Category 装载与附加机制</title><link>https://amatsuzero.github.io/LastStand/posts/ocsourcecodeanalysis/category-loading-explained/</link><pubDate>Mon, 01 Jun 2026 19:50:12 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/ocsourcecodeanalysis/category-loading-explained/</guid><description>&lt;p&gt;objc4 runtime&lt;/p&gt;
&lt;h1 id="category-装载与方法协议属性附加"&gt;Category 装载与方法、协议、属性附加&lt;/h1&gt;
&lt;p&gt;Category 的本质不是“修改类结构体”，而是在镜像加载和类实现化时，把分类携带的方法列表、协议列表、属性列表合并到目标类或元类的可变列表视图中。objc4 同时要处理未实现类、stub class、dyld 预附加列表、方法缓存失效和 &lt;code&gt;+load&lt;/code&gt; 顺序。&lt;/p&gt;
&lt;p&gt;runtime/objc-runtime-new.mm runtime/objc-runtime-new.h runtime/objc-loadmethod.mm test/category.m 等测试&lt;/p&gt;
&lt;h2 id="目录"&gt;目录&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="#purpose"&gt;作用&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#model"&gt;实现原理总览&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#structures"&gt;核心结构和字段&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#flow"&gt;关键流程&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#snippets"&gt;带注释核心代码&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#tests"&gt;测试揭示的行为&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;a id="purpose"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="作用"&gt;作用&lt;/h2&gt;
&lt;h3 id="扩展类行为"&gt;扩展类行为&lt;/h3&gt;
&lt;p&gt;分类把实例方法挂到类，把类方法挂到元类，让现有类获得新 selector 或覆盖既有 selector。&lt;/p&gt;
&lt;h3 id="扩展反射信息"&gt;扩展反射信息&lt;/h3&gt;
&lt;p&gt;分类的协议和属性参与 &lt;code&gt;class_copyProtocolList&lt;/code&gt;、&lt;code&gt;class_getProperty&lt;/code&gt; 等运行时查询。&lt;/p&gt;
&lt;h3 id="保持加载顺序"&gt;保持加载顺序&lt;/h3&gt;
&lt;p&gt;后加载的分类应优先被方法查找看到，所以列表附加采用“前插”。&lt;/p&gt;
&lt;h3 id="支持动态镜像"&gt;支持动态镜像&lt;/h3&gt;
&lt;p&gt;bundle、共享缓存、stub class 和未实现类都能在不同时间点接收分类。&lt;/p&gt;
&lt;p&gt;关键结论：分类附加不是把方法逐个复制进类定义，而是把 &lt;code&gt;method_list_t&lt;/code&gt;、&lt;code&gt;protocol_list_t&lt;/code&gt;、&lt;code&gt;property_list_t&lt;/code&gt; 这类“列表”挂到 &lt;code&gt;class_rw_ext_t&lt;/code&gt; 的数组视图前端。&lt;/p&gt;
&lt;p&gt;&lt;a id="model"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="实现原理总览"&gt;实现原理总览&lt;/h2&gt;
&lt;h3 id="mach-o-镜像"&gt;Mach-O 镜像&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;__objc_catlist&lt;/code&gt; / &lt;code&gt;__objc_catlist2&lt;/code&gt; 中保存 &lt;code&gt;category_t *&lt;/code&gt;。runtime 通过 &lt;code&gt;header_info&lt;/code&gt; 知道分类来自哪个镜像。&lt;/p&gt;
&lt;p&gt;→&lt;/p&gt;
&lt;h3 id="分类分流"&gt;分类分流&lt;/h3&gt;
&lt;p&gt;目标类未实现则暂存到 &lt;code&gt;unattachedCategories&lt;/code&gt;；目标类已实现则立即 &lt;code&gt;attachCategories&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;→&lt;/p&gt;
&lt;h3 id="列表前插"&gt;列表前插&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;attachLists&lt;/code&gt; 把新增列表放在旧列表前面，方法查找和反射会先看到分类列表。&lt;/p&gt;
&lt;p&gt;依据：&lt;code&gt;load_categories_nolock&lt;/code&gt; 分流逻辑见 runtime/objc-runtime-new.mm:3585-3717；列表前插见 runtime/objc-runtime-new.h:2021-2105。&lt;/p&gt;
&lt;p&gt;&lt;a id="structures"&gt;&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Kingfisher源码导读</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/kingfisher%E6%BA%90%E7%A0%81%E5%AF%BC%E8%AF%BB/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/kingfisher%E6%BA%90%E7%A0%81%E5%AF%BC%E8%AF%BB/</guid><description>&lt;p&gt;Kingfisher 是一款纯 Swift 图片下载和缓存库，支持 iOS、macOS、tvOS、watchOS 和 visionOS 全平台。当前最新版本为 &lt;strong&gt;8.8.0&lt;/strong&gt;（2026年3月），已全面适配 Swift 6 严格并发模型。本文基于 v8.x 源码进行分析。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="一整体架构"&gt;一、整体架构&lt;/h2&gt;
&lt;p&gt;Kingfisher 采用&lt;strong&gt;协议导向&lt;/strong&gt;的模块化设计，核心由四大组件构成：&lt;/p&gt;
&lt;pre class="mermaid"&gt;graph TB
subgraph "UI层"
A["UIImageView.kf / KFImage"]
end
subgraph "管理层"
B["KingfisherManager"]
end
subgraph "功能层"
C["ImageDownloader"]
D["ImageCache"]
E["ImageProcessor"]
end
subgraph "存储层"
F["MemoryStorage.Backend&lt;br/&gt;(NSCache)"]
G["DiskStorage.Backend&lt;br/&gt;(FileManager)"]
end
A --&gt;|"retrieveImage"| B
B --&gt;|"下载"| C
B --&gt;|"缓存"| D
B --&gt;|"处理"| E
D --&gt; F
D --&gt; G
&lt;/pre&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-gdscript3" data-lang="gdscript3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Sources&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 style="color:#960050;background-color:#1e0010"&gt;├──&lt;/span&gt; General&lt;span style="color:#f92672"&gt;/&lt;/span&gt; &lt;span style="color:#75715e"&gt;# KingfisherManager, KingfisherOptionsInfo, Resource, Source&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; Networking&lt;span style="color:#f92672"&gt;/&lt;/span&gt; &lt;span style="color:#75715e"&gt;# ImageDownloader, SessionDelegate, ImagePrefetcher&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; Cache&lt;span style="color:#f92672"&gt;/&lt;/span&gt; &lt;span style="color:#75715e"&gt;# ImageCache, MemoryStorage, DiskStorage&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:#a6e22e"&gt;Image&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt; &lt;span style="color:#75715e"&gt;# ImageProcessor, 图片格式处理, 滤镜&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; Extensions&lt;span style="color:#f92672"&gt;/&lt;/span&gt; &lt;span style="color:#75715e"&gt;# UIKit/AppKit 扩展 (ImageView+Kingfisher, UIButton+Kingfisher)&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; SwiftUI&lt;span style="color:#f92672"&gt;/&lt;/span&gt; &lt;span style="color:#75715e"&gt;# KFImage, KFAnimatedImage, ImageBinder&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; Views&lt;span style="color:#f92672"&gt;/&lt;/span&gt; &lt;span style="color:#75715e"&gt;# AnimatedImageView&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; Utility&lt;span style="color:#f92672"&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;hr&gt;
&lt;h2 id="二命名空间设计--kingfisherwrapper"&gt;二、命名空间设计 — KingfisherWrapper&lt;/h2&gt;
&lt;p&gt;Kingfisher 使用 &lt;code&gt;kf&lt;/code&gt; 命名空间来避免对系统类型的污染，这是 Swift 社区广泛使用的一种模式。&lt;/p&gt;</description></item><item><title>Swift 面试：编译流程、Runtime 与元数据源码解析</title><link>https://amatsuzero.github.io/LastStand/posts/swiftinterviewsourcecode/compiler-runtime/</link><pubDate>Tue, 16 Jun 2026 09:06:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/swiftinterviewsourcecode/compiler-runtime/</guid><description>&lt;h1 id="swift-面试编译流程runtime-与元数据源码解析"&gt;Swift 面试：编译流程、Runtime 与元数据源码解析&lt;/h1&gt;
&lt;p&gt;Swift 面试里问编译流程和 Runtime，通常不是想听一串名词，而是想看你能不能把 &lt;strong&gt;源码 -&amp;gt; AST -&amp;gt; SIL -&amp;gt; 优化 -&amp;gt; IRGen -&amp;gt; LLVM -&amp;gt; Runtime Metadata&lt;/strong&gt; 串起来。&lt;/p&gt;
&lt;p&gt;这篇文章按面试题展开，把答案落到 Swift 编译器源码里的 SILGen、SILOptimizer、IRGen、Metadata、Value Witness Table、Protocol Witness Table 和 HeapObject。&lt;/p&gt;
&lt;h2 id="面试高频问题"&gt;面试高频问题&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Swift 源码从 &lt;code&gt;.swift&lt;/code&gt; 到机器码经历哪些阶段？&lt;/li&gt;
&lt;li&gt;AST、SIL、LLVM IR 分别负责什么？&lt;/li&gt;
&lt;li&gt;为什么 Swift 需要 SIL，而不是直接生成 LLVM IR？&lt;/li&gt;
&lt;li&gt;SILGen 做什么？SILOptimizer 做什么？&lt;/li&gt;
&lt;li&gt;IRGen 为什么要生成 Metadata 和 Witness Table？&lt;/li&gt;
&lt;li&gt;Swift Runtime Metadata 保存了哪些信息？&lt;/li&gt;
&lt;li&gt;Value Witness Table 是什么？&lt;/li&gt;
&lt;li&gt;Protocol Witness Table 和 class vtable 有什么区别？&lt;/li&gt;
&lt;li&gt;class、struct、enum 在 Runtime 表示上有什么差异？&lt;/li&gt;
&lt;li&gt;HeapObject 和 Metadata 有什么关系？&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="30-秒回答版"&gt;30 秒回答版&lt;/h2&gt;
&lt;p&gt;Swift 编译流程可以简化为：&lt;/p&gt;</description></item><item><title>Objective-C +load 调度：load_images 与 call_load_methods</title><link>https://amatsuzero.github.io/LastStand/posts/ocsourcecodeanalysis/load-method-explained/</link><pubDate>Mon, 01 Jun 2026 19:50:12 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/ocsourcecodeanalysis/load-method-explained/</guid><description>&lt;p&gt;objc4 runtime&lt;/p&gt;
&lt;h1 id="load-调度从-load_images-到-call_load_methods"&gt;+load 调度：从 load_images 到 call_load_methods&lt;/h1&gt;
&lt;p&gt;这页解释 objc4 如何在 dyld 映射镜像后发现、排队并调用 Objective-C 的 &lt;code&gt;+load&lt;/code&gt;。 重点是类与分类的顺序、父类优先、递归和重入处理，以及 &lt;code&gt;runtimeLock&lt;/code&gt; 与 &lt;code&gt;loadMethodLock&lt;/code&gt; 的边界。&lt;/p&gt;
&lt;p&gt;入口：dyld callback 队列：loadable_classes / loadable_categories 调度：call_load_methods 测试：load*.m&lt;/p&gt;
&lt;h2 id="目录"&gt;目录&lt;/h2&gt;
&lt;p&gt;&lt;a href="#purpose"&gt;作用&lt;/a&gt; &lt;a href="#principle"&gt;实现原理&lt;/a&gt; &lt;a href="#structures"&gt;核心结构和关键函数&lt;/a&gt; &lt;a href="#flow"&gt;关键流程&lt;/a&gt; &lt;a href="#code"&gt;带注释代码片段&lt;/a&gt; &lt;a href="#tests"&gt;测试体现的语义&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="作用"&gt;作用&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;+load&lt;/code&gt; 是 Objective-C 运行时在类或分类被装入进程时主动调用的类方法。 它不依赖消息发送触发，也早于普通的 &lt;code&gt;+initialize&lt;/code&gt;。objc4 的任务不是简单遍历所有方法并调用， 而是在 dyld 映射镜像、runtime 完成类注册和分类附着后，按照语言语义和装载依赖稳定地调用。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;装载时机&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;dyld 通过 &lt;code&gt;_dyld_objc_register_callbacks&lt;/code&gt; 注册 runtime 回调。镜像映射后先走 &lt;code&gt;map_images&lt;/code&gt;，随后 &lt;code&gt;load_images&lt;/code&gt; 处理该镜像中的非懒加载类和分类。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;顺序语义&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;类 &lt;code&gt;+load&lt;/code&gt; 必须父类优先；所有当前可调用的类 &lt;code&gt;+load&lt;/code&gt; 先于分类 &lt;code&gt;+load&lt;/code&gt;；分类必须等宿主类已经完成自己的 &lt;code&gt;+load&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;重入安全&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;+load&lt;/code&gt; 内部可能 &lt;code&gt;dlopen&lt;/code&gt; 新镜像，再次进入 &lt;code&gt;load_images&lt;/code&gt;。objc4 让内层调用只排队，真正调用由最外层 &lt;code&gt;call_load_methods&lt;/code&gt; 收尾。&lt;/p&gt;
&lt;h2 id="实现原理"&gt;实现原理&lt;/h2&gt;
&lt;p&gt;objc4 将 &lt;code&gt;+load&lt;/code&gt; 分成“发现”和“调用”两阶段。发现阶段需要持有 &lt;code&gt;runtimeLock&lt;/code&gt;， 因为它要读取和实现类、解析分类、查找元类方法列表。调用阶段释放 &lt;code&gt;runtimeLock&lt;/code&gt;， 只持有递归的 &lt;code&gt;loadMethodLock&lt;/code&gt;，因为用户代码可能执行任意 Objective-C 行为并重新映射镜像。&lt;/p&gt;</description></item><item><title>RxSwift源码导读</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/rxswift%E6%BA%90%E7%A0%81%E5%AF%BC%E8%AF%BB/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/rxswift%E6%BA%90%E7%A0%81%E5%AF%BC%E8%AF%BB/</guid><description>&lt;p&gt;RxSwift 是 ReactiveX 在 Swift 上的实现，提供了一套完整的响应式编程框架。它通过 Observable 序列和操作符组合的方式，简化了异步编程、事件处理和数据流管理。本文基于 &lt;strong&gt;v6.10.2&lt;/strong&gt;（2026年3月发布）源码进行分析。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="一整体架构"&gt;一、整体架构&lt;/h2&gt;
&lt;p&gt;RxSwift 项目采用模块化设计，包含五个独立模块：&lt;/p&gt;
&lt;pre class="mermaid"&gt;graph TB
subgraph "核心层"
A["RxSwift&lt;br/&gt;核心响应式框架"]
end
subgraph "扩展层"
B["RxCocoa&lt;br/&gt;UIKit/AppKit绑定"]
C["RxRelay&lt;br/&gt;Relay封装"]
end
subgraph "工具层"
D["RxBlocking&lt;br/&gt;阻塞操作"]
E["RxTest&lt;br/&gt;测试工具"]
end
B --&gt; A
C --&gt; A
D --&gt; A
E --&gt; A
&lt;/pre&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-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;RxSwift/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── Concurrency/ # 并发工具（AsyncLock等）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── Disposables/ # 资源释放（DisposeBag、CompositeDisposable等）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── Extensions/ # Swift扩展
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── Observables/ # Observable实现（Create、Map、Filter、Merge等）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── Observers/ # Observer实现（AnonymousObserver、ObserverBase等）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── Platform/ # 平台适配（原子操作、锁等）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── Schedulers/ # 调度器（MainScheduler、SerialDispatchQueueScheduler等）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── Subjects/ # Subject实现（PublishSubject、BehaviorSubject等）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── SwiftSupport/ # Swift语言支持
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── Traits/ # 特化序列（Single、Completable、Maybe、Infallible）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── Observable.swift # Observable基类
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── ObservableType.swift # Observable协议
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── ObserverType.swift # Observer协议
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── Event.swift # 事件枚举
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── Disposable.swift # Disposable协议
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── Binder.swift # UI绑定
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── AnyObserver.swift # 类型擦除Observer
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;└── Reactive.swift # .rx命名空间
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;语言构成：&lt;/strong&gt; 纯 Swift 实现，100% Swift 代码。&lt;/p&gt;</description></item><item><title>+initialize 懒初始化与并发状态机</title><link>https://amatsuzero.github.io/LastStand/posts/ocsourcecodeanalysis/initialize-method-explained/</link><pubDate>Mon, 01 Jun 2026 19:50:12 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/ocsourcecodeanalysis/initialize-method-explained/</guid><description>&lt;p&gt;objc4 runtime 懒初始化 并发等待 fork safety&lt;/p&gt;
&lt;h1 id="initialize-懒初始化与并发状态机"&gt;+initialize 懒初始化与并发状态机&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;+initialize&lt;/code&gt; 是 Objective-C 运行时在类第一次被真正使用时触发的类级初始化钩子。 objc4 的实现重点不是“调用一个方法”，而是用每个类的递归初始化锁、元类上的状态位、线程本地的初始化列表和 fork 子进程保护规则，保证父类优先、单线程执行、并发可等待、重入不死锁。&lt;/p&gt;
&lt;h2 id="目录"&gt;目录&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="#purpose"&gt;作用&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#principle"&gt;实现原理&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#state"&gt;核心状态字段&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#entry"&gt;入口与触发&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#machine"&gt;并发状态机&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#flows"&gt;关键流程&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#tests"&gt;测试依据&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;a id="purpose"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="作用"&gt;作用&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;+initialize&lt;/code&gt; 的语义是：在某个类或其子类第一次收到会触发初始化的消息前，运行时先给该类发送一次 &lt;code&gt;+initialize&lt;/code&gt;。 这让类可以延迟建立全局状态、注册方法、准备缓存或执行只依赖本类的初始化逻辑。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;懒触发&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;objc_getClass()&lt;/code&gt; 只查找类，不触发初始化；普通消息发送、部分运行时查询、autorelease 返回值路径和弱引用相关路径可能需要先完成初始化。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;父类优先&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;子类开始初始化前，运行时递归确保父类已经初始化，避免类层次中间被并发线程插入造成死锁。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;一次完成&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;同一类只有一个线程真正发送 &lt;code&gt;+initialize&lt;/code&gt;；其他线程要么等待，要么在同一初始化线程重入时直接放行。&lt;/p&gt;
&lt;p&gt;&lt;a id="principle"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="实现原理"&gt;实现原理&lt;/h2&gt;
&lt;p&gt;objc4 把 &lt;code&gt;+initialize&lt;/code&gt; 做成一个按需进入的并发状态机：消息查找路径发现目标类未初始化时，先把类 realize，再释放 &lt;code&gt;runtimeLock&lt;/code&gt;，进入 &lt;code&gt;initializeNonMetaClass()&lt;/code&gt;。 后者用父类递归、每类递归锁、元类状态位和线程本地初始化列表协调所有线程。真正执行用户代码的线程设置 &lt;code&gt;INITIALIZING&lt;/code&gt;，发送 &lt;code&gt;+initialize&lt;/code&gt;，最后在 &lt;code&gt;@finally&lt;/code&gt; 中切换到 &lt;code&gt;INITIALIZED&lt;/code&gt;；其他线程通过同一把类锁等待状态稳定。&lt;/p&gt;
&lt;p&gt;这个设计的核心约束是单调性：类状态只从“未初始化”前进到“初始化中”，再前进到“已初始化”。即使 &lt;code&gt;+initialize&lt;/code&gt; 抛异常，状态机也会完成收尾；即使发生重入，只有当前初始化线程能绕过等待；即使 fork 发生在多线程初始化期间，子进程也只允许 trivial 初始化继续，其他自定义初始化会主动终止。&lt;/p&gt;
&lt;p&gt;&lt;a id="state"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="核心类结构状态字段"&gt;核心类/结构状态字段&lt;/h2&gt;
&lt;p&gt;初始化状态存在类对象的元类标志位里。源码注释明确约束：初始时 &lt;code&gt;RW_INITIALIZING&lt;/code&gt; 和 &lt;code&gt;RW_INITIALIZED&lt;/code&gt; 都未设置；初始化中只设置前者；完成后清除前者并设置后者；两者永不同时为真，且 &lt;code&gt;RW_INITIALIZED&lt;/code&gt; 一旦设置就不会清除。&lt;/p&gt;</description></item><item><title>SDWebImage源码导读</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/sdwebimage%E6%BA%90%E7%A0%81%E5%AF%BC%E8%AF%BB/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/sdwebimage%E6%BA%90%E7%A0%81%E5%AF%BC%E8%AF%BB/</guid><description>&lt;p&gt;SDWebImage 是 iOS 生态中历史最悠久、最流行的异步图片下载缓存库，由 Olivier Poitrey 在 2009 年创建，如今由社区维护。截至 2026 年 4 月，GitHub Star 数已超过 25.6k，最新稳定版本为 &lt;strong&gt;5.21.7&lt;/strong&gt;（2026 年 2 月）。5.21 系列引入了 HDR 图片编解码支持，并持续完善线程安全和 iOS 26 的兼容性。本文基于 master 分支源码（Objective-C 实现）进行分析。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="一整体架构"&gt;一、整体架构&lt;/h2&gt;
&lt;p&gt;SDWebImage 采用&lt;strong&gt;协议导向 + 责任链&lt;/strong&gt;的模块化设计，核心由五大子系统构成：Manager 协调层、Cache 缓存层、Downloader 下载层、Coder 编解码层和 UI 扩展层。&lt;/p&gt;
&lt;pre class="mermaid"&gt;graph TB
subgraph "UI 扩展层"
A["UIImageView+WebCache&lt;br/&gt;UIButton+WebCache&lt;br/&gt;UIView+WebCache"]
end
subgraph "管理层"
B["SDWebImageManager"]
end
subgraph "缓存层 SDImageCache"
C1["SDMemoryCache&lt;br/&gt;(NSCache + NSMapTable)"]
C2["SDDiskCache&lt;br/&gt;(NSFileManager)"]
end
subgraph "下载层"
D1["SDWebImageDownloader"]
D2["SDWebImageDownloaderOperation&lt;br/&gt;(NSOperation)"]
end
subgraph "编解码层 SDImageCodersManager"
E1["SDImageIOCoder"]
E2["SDImageGIFCoder"]
E3["SDImageAPNGCoder"]
E4["SDImageHEICCoder&lt;br/&gt;WebP/AVIF (插件)"]
end
subgraph "辅助层"
F["SDImageTransformer&lt;br/&gt;SDWebImageCacheKeyFilter&lt;br/&gt;SDWebImageOptionsProcessor&lt;br/&gt;SDCallbackQueue"]
end
A --&gt;|sd_setImageWithURL| B
B --&gt; C1
B --&gt; C2
B --&gt; D1
D1 --&gt; D2
D2 --&gt; E1
B --&gt; F
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;源码目录结构：&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>objc4 Selector / SEL 注册、唯一化与方法名查找</title><link>https://amatsuzero.github.io/LastStand/posts/ocsourcecodeanalysis/selector-interning-explained/</link><pubDate>Mon, 01 Jun 2026 19:50:12 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/ocsourcecodeanalysis/selector-interning-explained/</guid><description>&lt;h1 id="selector--sel-注册唯一化与方法名查找"&gt;Selector / SEL 注册、唯一化与方法名查找&lt;/h1&gt;
&lt;p&gt;在 objc4 中，&lt;code&gt;SEL&lt;/code&gt; 的关键价值不是承载一段复杂对象，而是把方法名字符串 “驻留”为全进程唯一的指针。注册、镜像加载 fixup、方法列表排序、方法查找和消息缓存都建立在这个事实上： 同名 selector 最终拥有同一个地址，因此比较 selector 可以退化为一次指针比较。&lt;/p&gt;
&lt;h2 id="作用"&gt;作用&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;统一方法名身份&lt;/strong&gt; 编译器、Mach-O 镜像、动态注册 API 和运行时内部方法列表都可能产生方法名。selector 唯一化后，同一个方法名只对应一个 &lt;code&gt;SEL&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;让查找足够便宜&lt;/strong&gt; 方法列表和缓存查找不需要反复比较字符串。命中条件基本都是 &lt;code&gt;method.name == sel&lt;/code&gt; 或 &lt;code&gt;bucket.sel == _cmd&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;支撑 dyld 预优化&lt;/strong&gt; 共享缓存中的 selector 可以由 dyld 提供内建唯一值；未优化镜像在 &lt;code&gt;_read_images&lt;/code&gt; 中被 runtime 修正到唯一值。&lt;/p&gt;
&lt;p&gt;对外头文件把 &lt;code&gt;SEL&lt;/code&gt; 声明为不透明类型：&lt;code&gt;typedef struct objc_selector *SEL;&lt;/code&gt;。 但在当前实现中，runtime 会把 selector 当成方法名 C 字符串指针使用，&lt;code&gt;sel_getName()&lt;/code&gt; 直接把 &lt;code&gt;SEL&lt;/code&gt; 转回 &lt;code&gt;const char *&lt;/code&gt;。&lt;/p&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;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SEL&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;公开为不透明 selector 指针，实际唯一值是某个方法名字符串的地址。来源：&lt;code&gt;runtime/objc.h&lt;/code&gt;。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;namedSelectors&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ExplicitInitDenseSet&amp;lt;const char *&amp;gt;&lt;/code&gt;，保存非 dyld 内建 selector 的唯一字符串指针。来源：&lt;code&gt;runtime/objc-sel.mm&lt;/code&gt;。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;selLock&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;保护 selector 表。&lt;code&gt;sel_registerName()&lt;/code&gt; 自行加锁；镜像加载和方法列表 fixup 常在外层持锁后调用 &lt;code&gt;sel_registerNameNoLock()&lt;/code&gt;。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;_sel_searchBuiltins()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;在支持预优化时向 dyld 查询共享缓存内建 selector，优先返回 dyld 已唯一化的值。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sel_registerName()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;注册并返回 selector；若已存在则返回既有唯一值；会复制传入字符串。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sel_lookUpByName()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;只查找，不创建。未注册返回 &lt;code&gt;NULL&lt;/code&gt;，测试 &lt;code&gt;test/sel.m&lt;/code&gt; 明确覆盖该行为。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;method_t::name&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;方法条目的 selector 字段。方法列表 fixup 后，这个字段应是唯一化的 &lt;code&gt;SEL&lt;/code&gt;。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cache_t&lt;/code&gt; / &lt;code&gt;bucket_t&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;消息缓存以 &lt;code&gt;SEL&lt;/code&gt; 为 key，桶保存 &lt;code&gt;SEL + IMP&lt;/code&gt;，hash 直接来自 selector 地址。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="实现原理"&gt;实现原理&lt;/h2&gt;
&lt;p&gt;selector interning 的核心是“先按名字查找唯一槽，再把槽里的字符串地址作为 &lt;code&gt;SEL&lt;/code&gt; 返回”。 对 dyld 共享缓存内建 selector，runtime 先问 dyld；对普通 selector，runtime 使用 &lt;code&gt;namedSelectors&lt;/code&gt; 保存唯一字符串。&lt;/p&gt;</description></item><item><title>SnapKit源码导读</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/snapkit%E6%BA%90%E7%A0%81%E5%AF%BC%E8%AF%BB/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/snapkit%E6%BA%90%E7%A0%81%E5%AF%BC%E8%AF%BB/</guid><description>&lt;p&gt;SnapKit 是 iOS / macOS 社区最广泛使用的 Auto Layout DSL 库，由 Robert Payne 等人维护，目前在 GitHub 已收获 &lt;strong&gt;20k+ star&lt;/strong&gt;。它在 &lt;code&gt;NSLayoutConstraint&lt;/code&gt; 之上构建了一整套链式、类型安全、面向协议的声明式约束语法。本文基于 &lt;strong&gt;v5.7.1&lt;/strong&gt;（2025 年 2 月发布，最后 master commit 2025-05-08 &lt;code&gt;19f59a6&lt;/code&gt;）源码进行分析，代码总量不足 &lt;strong&gt;3500 行&lt;/strong&gt;，却用一个分级的 Builder 链路，把 &lt;code&gt;NSLayoutConstraint&lt;/code&gt; 那套冗长的 API 封装成了今天我们习惯的 &lt;code&gt;make.left.equalTo(x).offset(10)&lt;/code&gt;。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="一整体架构"&gt;一、整体架构&lt;/h2&gt;
&lt;p&gt;SnapKit 的核心设计可以用一句话概括：&lt;strong&gt;用编译期强约束的链式 Builder，驱动一个延迟构建的 &lt;code&gt;ConstraintDescription&lt;/code&gt;，最终在闭包结束后一次性生成 &lt;code&gt;NSLayoutConstraint&lt;/code&gt; 并激活&lt;/strong&gt;。&lt;/p&gt;
&lt;pre class="mermaid"&gt;graph TB
subgraph "DSL 入口层"
V["UIView / NSView / UILayoutGuide"]
SNP["view.snp&lt;br/&gt;(ConstraintViewDSL)"]
MK["makeConstraints&lt;br/&gt;remakeConstraints&lt;br/&gt;updateConstraints"]
end
subgraph "Builder 链（阶段化构建器）"
CM["ConstraintMaker&lt;br/&gt;(属性起点 make.left)"]
CME["ConstraintMakerExtendable&lt;br/&gt;(追加属性 .top.right)"]
CMR["ConstraintMakerRelatable&lt;br/&gt;(关系 equalTo/greaterThan)"]
CMED["ConstraintMakerEditable&lt;br/&gt;(multipliedBy/offset/inset)"]
CMP["ConstraintMakerPrioritizable&lt;br/&gt;(priority)"]
CMF["ConstraintMakerFinalizable&lt;br/&gt;(labeled)"]
end
subgraph "描述 &amp; 协议层"
DESC["ConstraintDescription&lt;br/&gt;(懒加载装配)"]
TARGETS["Target 协议族&lt;br/&gt;Relatable/Constant/Offset&lt;br/&gt;Inset/Multiplier/Priority"]
ATTR["ConstraintAttributes&lt;br/&gt;(OptionSet 位运算)"]
end
subgraph "约束层"
C["Constraint&lt;br/&gt;(封装一组 LayoutConstraint)"]
LC["LayoutConstraint&lt;br/&gt;(NSLayoutConstraint 子类)"]
ITEM["LayoutConstraintItem&lt;br/&gt;(UIView/UILayoutGuide)"]
end
subgraph "系统层"
NSLC["NSLayoutConstraint.activate"]
end
V --&gt;|扩展属性| SNP
SNP --&gt; MK
MK --&gt;|创建| CM
CM --&gt;|返回| CME
CME --&gt;|继承| CMR
CMR --&gt;|equalTo| CMED
CMED --&gt;|继承| CMP
CMP --&gt;|priority| CMF
CM -.写入.-&gt; DESC
CME &amp; CMR &amp; CMED &amp; CMP &amp; CMF -.读写.-&gt; DESC
DESC -.lazy 构建.-&gt; C
C --&gt; LC
C -.关联对象.-&gt; ITEM
DESC -.使用.-&gt; ATTR
CMR -.类型匹配.-&gt; TARGETS
C --&gt; NSLC
&lt;/pre&gt;
&lt;h3 id="源码目录sources约-3500-行"&gt;源码目录（&lt;code&gt;Sources/&lt;/code&gt;，约 3500 行）&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-gdscript3" data-lang="gdscript3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Sources&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 style="color:#960050;background-color:#1e0010"&gt;├──&lt;/span&gt; ConstraintView&lt;span style="color:#f92672"&gt;.&lt;/span&gt;swift &lt;span style="color:#75715e"&gt;# typealias UIView/NSView → ConstraintView&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; ConstraintLayoutGuide&lt;span style="color:#f92672"&gt;.&lt;/span&gt;swift &lt;span style="color:#75715e"&gt;# typealias UILayoutGuide/NSLayoutGuide&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; ConstraintLayoutSupport&lt;span style="color:#f92672"&gt;.&lt;/span&gt;swift &lt;span style="color:#75715e"&gt;# typealias UILayoutSupport&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; Typealiases&lt;span style="color:#f92672"&gt;.&lt;/span&gt;swift &lt;span style="color:#75715e"&gt;# LayoutRelation / LayoutAttribute / LayoutPriority&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; ConstraintConfig&lt;span style="color:#f92672"&gt;.&lt;/span&gt;swift &lt;span style="color:#75715e"&gt;# interfaceLayoutDirection 全局开关&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; ConstraintView&lt;span style="color:#f92672"&gt;+&lt;/span&gt;Extensions&lt;span style="color:#f92672"&gt;.&lt;/span&gt;swift &lt;span style="color:#75715e"&gt;# view.snp 入口（含 snp_ 老别名）&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; ConstraintLayoutGuide&lt;span style="color:#f92672"&gt;+&lt;/span&gt;Extensions&lt;span style="color:#f92672"&gt;.&lt;/span&gt;swift &lt;span style="color:#75715e"&gt;# guide.snp 入口&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; UILayoutSupport&lt;span style="color:#f92672"&gt;+&lt;/span&gt;Extensions&lt;span style="color:#f92672"&gt;.&lt;/span&gt;swift &lt;span style="color:#75715e"&gt;# topLayoutGuide.snp（iOS 11 前）&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; ConstraintViewDSL&lt;span style="color:#f92672"&gt;.&lt;/span&gt;swift &lt;span style="color:#75715e"&gt;# makeConstraints / remake / update / remove&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; ConstraintLayoutGuideDSL&lt;span style="color:#f92672"&gt;.&lt;/span&gt;swift &lt;span style="color:#75715e"&gt;# LayoutGuide 版 DSL&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; ConstraintLayoutSupportDSL&lt;span style="color:#f92672"&gt;.&lt;/span&gt;swift &lt;span style="color:#75715e"&gt;# LayoutSupport 版 DSL&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; ConstraintDSL&lt;span style="color:#f92672"&gt;.&lt;/span&gt;swift &lt;span style="color:#75715e"&gt;# DSL 协议 + 属性定义（left/top/edges/...）&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; ConstraintMaker&lt;span style="color:#f92672"&gt;.&lt;/span&gt;swift &lt;span style="color:#75715e"&gt;# 属性起点（make.left / make.edges / ...）&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; ConstraintMakerExtendable&lt;span style="color:#f92672"&gt;.&lt;/span&gt;swift &lt;span style="color:#75715e"&gt;# 可追加属性（.top.right）&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; ConstraintMakerRelatable&lt;span style="color:#f92672"&gt;.&lt;/span&gt;swift &lt;span style="color:#75715e"&gt;# equalTo / lessThanOrEqual / greaterThanOrEqual&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; ConstraintMakerRelatable&lt;span style="color:#f92672"&gt;+&lt;/span&gt;Extensions&lt;span style="color:#f92672"&gt;.&lt;/span&gt;swift &lt;span style="color:#75715e"&gt;# equalToSuperview 闭包版&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; ConstraintMakerEditable&lt;span style="color:#f92672"&gt;.&lt;/span&gt;swift &lt;span style="color:#75715e"&gt;# multipliedBy / dividedBy / offset / inset&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; ConstraintMakerPrioritizable&lt;span style="color:#f92672"&gt;.&lt;/span&gt;swift &lt;span style="color:#75715e"&gt;# priority(...)&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; ConstraintMakerFinalizable&lt;span style="color:#f92672"&gt;.&lt;/span&gt;swift &lt;span style="color:#75715e"&gt;# labeled(...) + .constraint&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; ConstraintAttributes&lt;span style="color:#f92672"&gt;.&lt;/span&gt;swift &lt;span style="color:#75715e"&gt;# OptionSet 属性位图&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; ConstraintRelation&lt;span style="color:#f92672"&gt;.&lt;/span&gt;swift &lt;span style="color:#75715e"&gt;# equal / lessThanOrEqual / greaterThanOrEqual&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; ConstraintPriority&lt;span style="color:#f92672"&gt;.&lt;/span&gt;swift &lt;span style="color:#75715e"&gt;# required/high/medium/low&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; ConstraintDescription&lt;span style="color:#f92672"&gt;.&lt;/span&gt;swift &lt;span style="color:#75715e"&gt;# Builder 中间态 + lazy Constraint&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; ConstraintItem&lt;span style="color:#f92672"&gt;.&lt;/span&gt;swift &lt;span style="color:#75715e"&gt;# (target, attributes) 二元组（弱引用）&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; LayoutConstraintItem&lt;span style="color:#f92672"&gt;.&lt;/span&gt;swift &lt;span style="color:#75715e"&gt;# UIView/UILayoutGuide 统一协议&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; ConstraintInsets&lt;span style="color:#f92672"&gt;.&lt;/span&gt;swift &lt;span style="color:#75715e"&gt;# UIEdgeInsets typealias&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; ConstraintDirectionalInsets&lt;span style="color:#f92672"&gt;.&lt;/span&gt;swift &lt;span style="color:#75715e"&gt;# NSDirectionalEdgeInsets（iOS 11+）&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; ConstraintRelatableTarget&lt;span style="color:#f92672"&gt;.&lt;/span&gt;swift &lt;span style="color:#75715e"&gt;# 可作为 equalTo 参数的类型标记&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; ConstraintConstantTarget&lt;span style="color:#f92672"&gt;.&lt;/span&gt;swift &lt;span style="color:#75715e"&gt;# constant 目标 + 属性→CGFloat 的派发&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; ConstraintOffsetTarget&lt;span style="color:#f92672"&gt;.&lt;/span&gt;swift &lt;span style="color:#75715e"&gt;# offset 目标&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; ConstraintInsetTarget&lt;span style="color:#f92672"&gt;.&lt;/span&gt;swift &lt;span style="color:#75715e"&gt;# inset 目标（含标量→insets 转换）&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; ConstraintDirectionalInsetTarget&lt;span style="color:#f92672"&gt;.&lt;/span&gt;swift &lt;span style="color:#75715e"&gt;# 方向 insets 目标&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; ConstraintMultiplierTarget&lt;span style="color:#f92672"&gt;.&lt;/span&gt;swift &lt;span style="color:#75715e"&gt;# multiplier 目标&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; ConstraintPriorityTarget&lt;span style="color:#f92672"&gt;.&lt;/span&gt;swift &lt;span style="color:#75715e"&gt;# priority 目标（Int/Float/UILayoutPriority）&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; Constraint&lt;span style="color:#f92672"&gt;.&lt;/span&gt;swift &lt;span style="color:#75715e"&gt;# 真正的约束对象 + activate/deactivate&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; LayoutConstraint&lt;span style="color:#f92672"&gt;.&lt;/span&gt;swift &lt;span style="color:#75715e"&gt;# NSLayoutConstraint 子类，回指 Constraint&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; Debugging&lt;span style="color:#f92672"&gt;.&lt;/span&gt;swift &lt;span style="color:#75715e"&gt;# LayoutConstraint.description 美化&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; PrivacyInfo&lt;span style="color:#f92672"&gt;.&lt;/span&gt;xcprivacy &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="核心设计思想"&gt;核心设计思想&lt;/h3&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;strong&gt;阶段化 Builder&lt;/strong&gt;（Staged Builder / Step Builder）&lt;/td&gt;
&lt;td&gt;通过继承链控制链式调用的合法顺序，让 &lt;code&gt;make.left.offset(10).equalTo(...)&lt;/code&gt; 这类非法组合在编译期报错&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ConstraintMaker → Extendable → Relatable → Editable → Prioritizable → Finalizable&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;协议 + 类型擦除&lt;/strong&gt;（POP）&lt;/td&gt;
&lt;td&gt;让 &lt;code&gt;Int / Float / CGFloat / CGSize / CGPoint / UIEdgeInsets / UIView / ConstraintItem&lt;/code&gt; 等异构类型可以统一作为 &lt;code&gt;equalTo&lt;/code&gt; / &lt;code&gt;offset&lt;/code&gt; / &lt;code&gt;priority&lt;/code&gt; 的参数&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Constraint*Target&lt;/code&gt; 协议族&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;OptionSet 位运算&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;用 32 位整型表达「属性集合」，&lt;code&gt;.edges = [.left, .top, .right, .bottom]&lt;/code&gt; 这类聚合用位或实现，避免反复建数组&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ConstraintAttributes&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Associated Object&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;在不污染 &lt;code&gt;UIView&lt;/code&gt; 原类的前提下，为每个 View 绑定「它持有的 SnapKit Constraint 集合」和「snp.label」&lt;/td&gt;
&lt;td&gt;&lt;code&gt;LayoutConstraintItem.constraintsSet&lt;/code&gt; + &lt;code&gt;ConstraintDSL.setLabel&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Lazy 求值&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ConstraintDescription.constraint&lt;/code&gt; 是 &lt;code&gt;lazy var&lt;/code&gt;，闭包执行结束前只是收集参数，真正的 &lt;code&gt;Constraint&lt;/code&gt; 构造和 &lt;code&gt;NSLayoutConstraint&lt;/code&gt; 生成都推迟到最后&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ConstraintDescription.constraint&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;跨平台 typealias&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;通过一组 typealias 把 iOS / macOS / tvOS 的 &lt;code&gt;UIView&lt;/code&gt;/&lt;code&gt;NSView&lt;/code&gt;、&lt;code&gt;UIEdgeInsets&lt;/code&gt;/&lt;code&gt;NSEdgeInsets&lt;/code&gt;、&lt;code&gt;UILayoutPriority&lt;/code&gt;/&lt;code&gt;NSLayoutConstraint.Priority&lt;/code&gt; 等抹平&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ConstraintView.swift&lt;/code&gt; / &lt;code&gt;Typealiases.swift&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="二dsl-入口viewsnp"&gt;二、DSL 入口：&lt;code&gt;view.snp&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;SnapKit 没有像 Masonry 那样污染 &lt;code&gt;UIView&lt;/code&gt; 的命名空间，而是通过一个&lt;strong&gt;命名空间结构体&lt;/strong&gt;暴露 DSL。&lt;/p&gt;</description></item><item><title>objc4 Protocol 结构、注册与查询</title><link>https://amatsuzero.github.io/LastStand/posts/ocsourcecodeanalysis/protocol-runtime-explained/</link><pubDate>Mon, 01 Jun 2026 19:50:12 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/ocsourcecodeanalysis/protocol-runtime-explained/</guid><description>&lt;h2 id="目录"&gt;目录&lt;/h2&gt;
&lt;p&gt;&lt;a href="#role"&gt;1. Protocol 的作用&lt;/a&gt; &lt;a href="#model"&gt;2. 核心结构&lt;/a&gt; &lt;a href="#load"&gt;3. read_images 读取协议&lt;/a&gt; &lt;a href="#remap"&gt;4. remap 与重复协议&lt;/a&gt; &lt;a href="#query"&gt;5. 查询与 conforms 判断&lt;/a&gt; &lt;a href="#dynamic"&gt;6. 动态创建与注册&lt;/a&gt; &lt;a href="#tests"&gt;7. 测试体现的行为&lt;/a&gt; &lt;a href="#summary"&gt;8. 总结&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="1-protocol-的作用"&gt;1. Protocol 的作用&lt;/h2&gt;
&lt;p&gt;在 objc4 中，&lt;code&gt;Protocol *&lt;/code&gt; 并不是一个只有名字的轻量句柄，而是运行时管理的一类 Objective-C 对象。 它承载协议名、继承的协议列表、必需/可选方法列表、实例/类属性列表等元数据。类、分类和协议自身都可以引用这些对象。&lt;/p&gt;
&lt;p&gt;对外 API 位于 &lt;code&gt;runtime/runtime.h&lt;/code&gt; 的 “Working with Protocols” 区域，例如 &lt;code&gt;objc_getProtocol&lt;/code&gt;、&lt;code&gt;objc_copyProtocolList&lt;/code&gt;、&lt;code&gt;protocol_conformsToProtocol&lt;/code&gt;、 &lt;code&gt;protocol_getMethodDescription&lt;/code&gt;、&lt;code&gt;objc_allocateProtocol&lt;/code&gt; 与 &lt;code&gt;objc_registerProtocol&lt;/code&gt;。 &lt;code&gt;runtime/Protocol.mm&lt;/code&gt; 中的 &lt;code&gt;@implementation Protocol&lt;/code&gt; 则把老式 Objective-C 消息转接到这些 C API。&lt;/p&gt;
&lt;p&gt;关键心智模型：编译器把协议写进镜像的 &lt;code&gt;__objc_protolist&lt;/code&gt; 等段；runtime 在 &lt;code&gt;_read_images&lt;/code&gt; 中发现并安装协议； 后续所有查询都尽量通过“协议名 =&amp;gt; 胜出的协议对象”来回到唯一的、当前有效的定义。&lt;/p&gt;
&lt;h2 id="2-核心结构"&gt;2. 核心结构&lt;/h2&gt;
&lt;p&gt;当前实现中的底层结构定义在 &lt;code&gt;runtime/objc-runtime-new.h&lt;/code&gt;。公开的 &lt;code&gt;Protocol *&lt;/code&gt; 在实现里经常通过 &lt;code&gt;newprotocol(p)&lt;/code&gt; 转成 &lt;code&gt;protocol_t *&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-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// runtime/objc-runtime-new.h，保留关键字段并加注释
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;typedef&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;uintptr_t&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;protocol_ref_t&lt;/span&gt;; &lt;span style="color:#75715e"&gt;// 尚未 remap 的 protocol_t *
&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:#a6e22e"&gt;struct&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;protocol_t&lt;/span&gt; &lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;objc_object&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;char&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;mangledName&lt;/span&gt;; &lt;span style="color:#75715e"&gt;// 协议的运行时名字；Swift v1 可能是 mangled 名
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;struct&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;protocol_list_t&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;protocols&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:#a6e22e"&gt;method_list_t&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;instanceMethods&lt;/span&gt;; &lt;span style="color:#75715e"&gt;// @required 实例方法
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;method_list_t&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;classMethods&lt;/span&gt;; &lt;span style="color:#75715e"&gt;// @required 类方法
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;method_list_t&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;optionalInstanceMethods&lt;/span&gt;; &lt;span style="color:#75715e"&gt;// @optional 实例方法
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;method_list_t&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;optionalClassMethods&lt;/span&gt;; &lt;span style="color:#75715e"&gt;// @optional 类方法
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;property_list_t&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;instanceProperties&lt;/span&gt;; &lt;span style="color:#75715e"&gt;// required instance properties
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;uint32_t&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;size&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:#a6e22e"&gt;uint32_t&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;flags&lt;/span&gt;; &lt;span style="color:#75715e"&gt;// fixed-up、canonical 等运行时标志
&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;// 以下字段不是所有磁盘协议结构都有，访问前必须看 size。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;char&lt;/span&gt; &lt;span style="color:#f92672"&gt;**&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_extendedMethodTypes&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;const&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;char&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_demangledName&lt;/span&gt;; &lt;span style="color:#75715e"&gt;// Swift demangled 名称缓存
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;property_list_t&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;_classProperties&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:#a6e22e"&gt;struct&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;protocol_list_t&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;uintptr_t&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;count&lt;/span&gt;; &lt;span style="color:#75715e"&gt;// 历史原因：count 是指针宽度
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;protocol_ref_t&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;list&lt;/span&gt;[&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;]; &lt;span style="color:#75715e"&gt;// 变长数组；元素可能需要 remap
&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="关键字段与方法"&gt;关键字段与方法&lt;/h3&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;&lt;code&gt;mangledName&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;全局协议表的 key。&lt;code&gt;objc_getProtocol&lt;/code&gt; 先按原名查，再查 dyld 预优化表，再尝试 Swift v1 mangled 等价名。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;protocols&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;协议继承关系。&lt;code&gt;protocol_conformsToProtocol&lt;/code&gt; 会递归遍历它；&lt;code&gt;protocol_copyProtocolList&lt;/code&gt; 只复制直接继承项。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;四个方法列表&lt;/td&gt;
&lt;td&gt;按 required/optional 与 instance/class 分成四组。&lt;code&gt;protocol_copyMethodDescriptionList&lt;/code&gt; 只返回当前协议直接声明的方法，不包含父协议。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;size&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;兼容小协议或旧 ABI 的关键字段。&lt;code&gt;protocolSmall.m&lt;/code&gt; 手工构造较小结构，验证访问尾部字段前必须判定字段是否存在。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;flags&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;高位用于 &lt;code&gt;PROTOCOL_FIXED_UP_*&lt;/code&gt; 与 &lt;code&gt;PROTOCOL_IS_CANONICAL&lt;/code&gt;，标记是否已修正以及共享缓存中的 canonical 定义。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="protocol-类"&gt;&lt;code&gt;Protocol&lt;/code&gt; 类&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;runtime/Protocol.h&lt;/code&gt; 只暴露不可直接使用的 &lt;code&gt;@interface Protocol&lt;/code&gt;； &lt;code&gt;Protocol.mm&lt;/code&gt; 中 &lt;code&gt;-conformsTo:&lt;/code&gt;、&lt;code&gt;-name&lt;/code&gt;、&lt;code&gt;-isEqual:&lt;/code&gt; 分别调用 &lt;code&gt;protocol_conformsToProtocol&lt;/code&gt;、&lt;code&gt;protocol_getName&lt;/code&gt; 与 &lt;code&gt;protocol_isEqual&lt;/code&gt;。&lt;/p&gt;</description></item><item><title>Swinject源码导读</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/swinject%E6%BA%90%E7%A0%81%E5%AF%BC%E8%AF%BB/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/swinject%E6%BA%90%E7%A0%81%E5%AF%BC%E8%AF%BB/</guid><description>&lt;p&gt;Swinject 是一款轻量级的 Swift 依赖注入（Dependency Injection）框架，灵感来自 .NET 的 Ninject。它通过&lt;strong&gt;类型安全的方式&lt;/strong&gt;管理对象之间的依赖关系，将对象的创建和使用解耦。本文基于 &lt;strong&gt;v2.8.3&lt;/strong&gt; 源码进行分析。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="一整体架构"&gt;一、整体架构&lt;/h2&gt;
&lt;p&gt;Swinject 的核心设计围绕**注册-解析（Register-Resolve）**模式展开，整个框架仅约 20 个源码文件，代码极为精简。&lt;/p&gt;
&lt;pre class="mermaid"&gt;graph TB
subgraph "组织层"
A["Assembler"]
B["Assembly (Protocol)"]
end
subgraph "核心层"
C["Container"]
D["Resolver (Protocol)"]
end
subgraph "注册层"
E["ServiceEntry&amp;lt;Service&amp;gt;"]
F["ServiceKey"]
end
subgraph "作用域层"
G["ObjectScope"]
H["InstanceStorage (Protocol)"]
end
subgraph "存储实现"
I["TransientStorage"]
J["GraphStorage"]
K["PermanentStorage"]
L["WeakStorage"]
end
subgraph "包装器"
M["Lazy&amp;lt;Service&amp;gt;"]
N["Provider&amp;lt;Service&amp;gt;"]
end
A --&gt;|"管理"| B
B --&gt;|"assemble(container:)"| C
C --&gt;|"实现"| D
C --&gt;|"存储注册信息"| E
E --&gt;|"由 ServiceKey 索引"| F
E --&gt;|"关联"| G
G --&gt;|"创建"| H
H --- I
H --- J
H --- K
H --- L
C --&gt;|"延迟解析"| M
C --&gt;|"每次新建"| N
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;源码文件结构：&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>Tagged Pointer 对象实现讲解</title><link>https://amatsuzero.github.io/LastStand/posts/ocsourcecodeanalysis/tagged-pointer-explained/</link><pubDate>Mon, 01 Jun 2026 19:50:12 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/ocsourcecodeanalysis/tagged-pointer-explained/</guid><description>&lt;p&gt;objc4 runtime internals&lt;/p&gt;
&lt;h1 id="tagged-pointer-对象"&gt;Tagged Pointer 对象&lt;/h1&gt;
&lt;p&gt;Tagged Pointer 是一种“指针即对象”的表示法：对象没有堆内存，类信息和 payload 直接编码在指针位中。objc4 对它提供了创建、取 tag、取 payload、取类、消息发送、禁用和混淆等完整路径。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;目录&lt;/strong&gt; &lt;a href="#why"&gt;作用&lt;/a&gt; &lt;a href="#layout"&gt;实现原理&lt;/a&gt; &lt;a href="#symbols"&gt;核心宏、结构、函数&lt;/a&gt; &lt;a href="#flows"&gt;关键流程&lt;/a&gt; &lt;a href="#tests"&gt;测试视角&lt;/a&gt; &lt;a href="#sources"&gt;源码依据&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="作用"&gt;作用&lt;/h2&gt;
&lt;h3 id="减少堆分配"&gt;减少堆分配&lt;/h3&gt;
&lt;p&gt;小整数、短字符串、日期、索引路径等小对象可以直接塞进指针。&lt;code&gt;NSNumber&lt;/code&gt; 的小整数就是典型例子，&lt;code&gt;test/taggedNSPointers.m&lt;/code&gt; 验证了 &lt;code&gt;NSNumber numberWithInt:1234&lt;/code&gt; 是 tagged pointer。&lt;/p&gt;
&lt;h3 id="保留对象语义"&gt;保留对象语义&lt;/h3&gt;
&lt;p&gt;虽然指针不指向对象内存，它仍能接收消息、查询类、作为字典 key/value，并通过 Foundation/CF 桥接。运行时把 tag 映射到真实 Class 后，继续走常规方法缓存查找。&lt;/p&gt;
&lt;h3 id="绕开生命周期表"&gt;绕开生命周期表&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;test/taggedPointers.m&lt;/code&gt; 验证 retain、release、autorelease、weak store/load 对 tagged pointer 不产生真实引用计数或弱引用表负担。它们本质上是立即值，不需要释放。&lt;/p&gt;
&lt;p&gt;**一句话：**Tagged Pointer 把“对象身份”改成“位编码值”。运行时需要做的，是在所有需要对象元数据的地方识别它，并把 tag 翻译成类。&lt;/p&gt;
&lt;h2 id="实现原理"&gt;实现原理&lt;/h2&gt;
&lt;p&gt;objc4 在 64 位平台启用 tagged pointer。&lt;code&gt;runtime/objc-config.h&lt;/code&gt; 中 &lt;code&gt;SUPPORT_TAGGED_POINTERS&lt;/code&gt; 对 &lt;code&gt;__LP64__&lt;/code&gt; 为 1；非 64 位平台关闭。tag 标记位在大多数平台使用 MSB，macOS x86_64 使用 LSB。arm64 还使用 split tagged pointer 布局。&lt;/p&gt;</description></item><item><title>Texture源码导读</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/texture%E6%BA%90%E7%A0%81%E5%AF%BC%E8%AF%BB/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/texture%E6%BA%90%E7%A0%81%E5%AF%BC%E8%AF%BB/</guid><description>&lt;blockquote&gt;
&lt;p&gt;TODO: 待补充&lt;/p&gt;
&lt;/blockquote&gt;</description></item><item><title>objc4：isa_t、nonpointer isa、引用计数与 SideTable</title><link>https://amatsuzero.github.io/LastStand/posts/ocsourcecodeanalysis/isa-refcount-explained/</link><pubDate>Mon, 01 Jun 2026 19:50:12 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/ocsourcecodeanalysis/isa-refcount-explained/</guid><description>&lt;h1 id="isa_tnonpointer-isa引用计数与-sidetable"&gt;isa_t、nonpointer isa、引用计数与 SideTable&lt;/h1&gt;
&lt;p&gt;本文基于 objc4 仓库中的 runtime 源码和相关测试，解释 Objective-C 对象头里的 &lt;code&gt;isa_t&lt;/code&gt; 如何同时承载类信息、引用计数、弱引用/关联对象标记，以及这些信息何时转移到 &lt;code&gt;SideTable&lt;/code&gt;。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#role"&gt;作用&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#layout"&gt;实现原理与位布局&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#structures"&gt;核心结构和关键字段方法&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#flows"&gt;关键流程&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#tests"&gt;测试如何约束行为&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="1-作用"&gt;1. 作用&lt;/h2&gt;
&lt;p&gt;传统 Objective-C 对象的第一个机器字是 &lt;code&gt;isa&lt;/code&gt;，直接保存类指针。objc4 在支持 &lt;code&gt;SUPPORT_NONPOINTER_ISA&lt;/code&gt; 的平台上把这个机器字扩展为 &lt;code&gt;isa_t&lt;/code&gt;： 低位和高位保存状态，中间区域保存类信息。这样一次对象头访问就能拿到类、内联引用计数、 是否有弱引用、是否有关联对象、是否可能有 C++ 析构等信息。&lt;/p&gt;
&lt;h3 id="为什么要-nonpointer-isa"&gt;为什么要 nonpointer isa&lt;/h3&gt;
&lt;p&gt;对象绝大多数时候引用计数很小，把计数放进 &lt;code&gt;isa&lt;/code&gt; 可让 retain/release 走原子 CAS 快路径，避免进入全局散列表和锁。&lt;/p&gt;
&lt;h3 id="为什么仍需要-sidetable"&gt;为什么仍需要 SideTable&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;isa&lt;/code&gt; 空间有限。引用计数溢出、raw isa 对象、弱引用表，以及 deallocating 状态的兼容存储，都需要 &lt;code&gt;SideTable&lt;/code&gt;。&lt;/p&gt;
&lt;h3 id="raw-isa-的存在原因"&gt;raw isa 的存在原因&lt;/h3&gt;
&lt;p&gt;类对象始终使用 raw pointer isa；某些类通过 &lt;code&gt;instancesRequireRawIsa()&lt;/code&gt; 或 运行时配置禁用 nonpointer isa；测试 &lt;code&gt;rawisa.m&lt;/code&gt; 还覆盖了 &lt;code&gt;__DATA,__objc_rawisa&lt;/code&gt; 段禁用 nonpointer isa 的场景。&lt;/p&gt;</description></item><item><title>fishhook 源码导读</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/fishhook%E6%BA%90%E7%A0%81%E5%AF%BC%E8%AF%BB/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/fishhook%E6%BA%90%E7%A0%81%E5%AF%BC%E8%AF%BB/</guid><description>&lt;blockquote&gt;
&lt;p&gt;fishhook 由 Facebook 于 2013 年开源，用于在运行时动态重绑定（rebind）Mach-O 中被 dyld 绑定的 C 符号，是 iOS/macOS 逆向与底层埋点（malloc 追踪、双 close 检测、网络 socket 拦截、NSLog 重定向等）领域的&amp;quot;瑞士军刀&amp;quot;。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一fishhook-是什么"&gt;一、fishhook 是什么&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;一句话定义&lt;/strong&gt;：fishhook 通过修改 Mach-O 镜像中 &lt;code&gt;__DATA(_CONST)&lt;/code&gt; 段里 &lt;code&gt;__la_symbol_ptr&lt;/code&gt; / &lt;code&gt;__nl_symbol_ptr&lt;/code&gt; 两个 Section 中的函数指针，把对外部 C 符号（如 &lt;code&gt;open&lt;/code&gt;、&lt;code&gt;close&lt;/code&gt;、&lt;code&gt;NSLog&lt;/code&gt;）的调用重定向到自定义的替换函数，同时保留原函数指针供回调使用。&lt;/p&gt;
&lt;p&gt;它提供的能力类似 macOS 上 &lt;code&gt;DYLD_INTERPOSE&lt;/code&gt; 宏（编译期 interpose），但：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;运行时生效&lt;/strong&gt;：不需要重新编译依赖库，随时可以在 App 启动后对系统库的 C 函数下钩子；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;支持动态加载的 image&lt;/strong&gt;：注册后对后续 &lt;code&gt;dlopen&lt;/code&gt; 加载的 image 同样生效；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;对业务零侵入&lt;/strong&gt;：不改 App 本身的代码段，也不破坏符号表，只是重写 GOT/stub 里的一个指针。&lt;/li&gt;
&lt;/ul&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;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Hook 通过 &lt;code&gt;dyld&lt;/code&gt; 动态绑定的外部 C 函数（libSystem、CoreFoundation 里的 C API、&lt;code&gt;objc_msgSend&lt;/code&gt; 等）&lt;/td&gt;
&lt;td&gt;是&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hook Objective-C 方法（&lt;code&gt;-[NSString length]&lt;/code&gt;）&lt;/td&gt;
&lt;td&gt;否（要用 Method Swizzling）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hook 当前 image 内部的 C 函数（静态链接、&lt;code&gt;static&lt;/code&gt;、内联）&lt;/td&gt;
&lt;td&gt;否（它不走 &lt;code&gt;__la_symbol_ptr&lt;/code&gt;，直接是段内相对寻址）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hook Swift 方法（除非显式 &lt;code&gt;@_cdecl&lt;/code&gt;）&lt;/td&gt;
&lt;td&gt;否&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hook 已经解析并内联到寄存器里的符号（如 LTO 后消失的符号）&lt;/td&gt;
&lt;td&gt;否&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;记住这条原则：&lt;strong&gt;fishhook 的作用域 = 被 dyld 绑定为&amp;quot;间接符号&amp;quot;（Indirect Symbol）的 C 符号&lt;/strong&gt;。&lt;/p&gt;</description></item><item><title>Objective-C weak 指针作用与实现原理</title><link>https://amatsuzero.github.io/LastStand/posts/ocsourcecodeanalysis/weak-pointer-explained/</link><pubDate>Mon, 01 Jun 2026 19:50:12 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/ocsourcecodeanalysis/weak-pointer-explained/</guid><description>&lt;p&gt;objc4 runtime zeroing weak SideTable weak_table_t&lt;/p&gt;
&lt;h1 id="objective-c-weak-指针作用与实现原理"&gt;Objective-C weak 指针：作用与实现原理&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;__weak&lt;/code&gt; 的核心价值是“引用对象但不拥有对象”：它不会增加引用计数；当对象开始销毁时，runtime 会把所有指向它的 weak 槽位自动写成 &lt;code&gt;nil&lt;/code&gt;，避免野指针。这一页按 objc4 源码中的真实路径解释它如何登记、读取、搬迁和清零。&lt;/p&gt;
&lt;p&gt;&lt;a id="role"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="阅读顺序"&gt;阅读顺序&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="#role"&gt;weak 解决什么问题&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#model"&gt;运行时数据模型&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#api"&gt;核心类型、字段、方法&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#flows"&gt;关键操作流程&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#snippets"&gt;带注释源码片段&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#summary"&gt;一遍记住&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;a id="model"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="1-weak-的作用"&gt;1. weak 的作用&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;不拥有对象&lt;/strong&gt;&lt;code&gt;__weak id x = obj;&lt;/code&gt; 不会 retain &lt;code&gt;obj&lt;/code&gt;，所以不会延长对象生命周期。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;自动归零&lt;/strong&gt;对象销毁时，所有保存该对象地址的 weak 变量会被 runtime 写成 &lt;code&gt;nil&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;读时短暂保活&lt;/strong&gt;读取 weak 时，runtime 会先尝试 retain，再 autorelease，保证表达式使用期间对象不被并发释放。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;拒绝无效目标&lt;/strong&gt;目标正在 dealloc 或类不支持 weak 时，形成 weak 引用会失败或崩溃，取决于入口函数。&lt;/p&gt;
&lt;p&gt;**一句话模型：**strong 指针管“拥有关系”，weak 指针管“可观察关系”。delegate、反向引用、缓存回调对象通常适合 weak，因为它们不应该阻止真实所有者释放对象。&lt;/p&gt;
&lt;p&gt;&lt;a id="api"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="2-运行时数据模型"&gt;2. 运行时数据模型&lt;/h2&gt;
&lt;p&gt;weak 表不是全局一把大表直接裸用，而是挂在分片的 &lt;code&gt;SideTable&lt;/code&gt; 上。runtime 用对象地址选择某个 &lt;code&gt;SideTable&lt;/code&gt;，在该表内维护引用计数辅助信息和 weak 表，并用同一把锁保护它们。&lt;/p&gt;</description></item><item><title>CocoaPods 源码导读：从下载到工程集成</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/cocoapods-%E4%BB%8E%E4%B8%8B%E8%BD%BD%E5%88%B0%E5%B7%A5%E7%A8%8B%E9%9B%86%E6%88%90/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/cocoapods-%E4%BB%8E%E4%B8%8B%E8%BD%BD%E5%88%B0%E5%B7%A5%E7%A8%8B%E9%9B%86%E6%88%90/</guid><description>&lt;blockquote&gt;
&lt;p&gt;本文是系列第三篇，基于 CocoaPods 1.16.2 源码。上一篇我们停在 &lt;code&gt;Analyzer&lt;/code&gt; 产出 &lt;code&gt;AnalysisResult&lt;/code&gt;，本文继续走完 &lt;code&gt;download_dependencies&lt;/code&gt; → &lt;code&gt;validate_targets&lt;/code&gt; → &lt;code&gt;generate_pods_project&lt;/code&gt; → &lt;code&gt;integrate_user_project&lt;/code&gt; → &lt;code&gt;write_lockfiles&lt;/code&gt; 这五个阶段。&lt;/p&gt;
&lt;p&gt;上一篇：&lt;a href="https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/cocoapods-%E4%BB%8E%E5%91%BD%E4%BB%A4%E5%88%B0%E4%BE%9D%E8%B5%96%E6%B1%82%E8%A7%A3/"&gt;从命令到依赖求解&lt;/a&gt; · 首篇：&lt;a href="https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/cocoapods-%E6%9E%B6%E6%9E%84%E6%80%BB%E8%A7%88/"&gt;架构总览&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一全景从-spec-到可编译的工程"&gt;一、全景：从 spec 到可编译的工程&lt;/h2&gt;
&lt;p&gt;先把本文要走的流程重新放一遍，让你带着地图读代码：&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart TB
A[AnalysisResult] --&gt; B[download_dependencies]
B --&gt;|per pod| B1[PodSourceDownloader]
B1 --&gt;|命中| C1[Downloader::Cache]
B1 --&gt;|未命中| C2[cocoapods-downloader&lt;br/&gt;Git/HTTP/SVN/...]
C2 --&gt; C3[rsync → Pods/&amp;lt;name&amp;gt;/]
B --&gt;|per pod| B2[PodSourceInstaller]
B2 --&gt; B3[PodSourcePreparer&lt;br/&gt;prepare_command]
B2 --&gt; B4[PodDirCleaner&lt;br/&gt;按 spec.source_files 裁剪]
B --&gt; D[validate_targets&lt;br/&gt;TargetValidator#validate!]
D --&gt; E[generate_pods_project]
E --&gt; E1[ProjectCacheAnalyzer&lt;br/&gt;增量识别要重生成的 target]
E --&gt; E2[SinglePodsProjectGenerator#generate!]
E2 --&gt; E21[FileReferencesInstaller]
E2 --&gt; E22[PodTargetInstaller]
E2 --&gt; E23[AggregateTargetInstaller]
E2 --&gt; E24[xcconfig / modulemap / umbrella / info.plist / dummy.m]
E --&gt; E3[PodsProjectWriter#write!&lt;br/&gt;写盘前触发 Podfile post_install]
E --&gt; F[integrate_user_project]
F --&gt; F1[create_workspace&lt;br/&gt;写 .xcworkspace]
F --&gt; F2[deintegrate_removed_targets]
F --&gt; F3[TargetIntegrator#integrate!&lt;br/&gt;xcconfig / frameworks / scripts]
F --&gt; G[write_lockfiles]
G --&gt; G1[Podfile.lock]
G --&gt; G2[Pods/Manifest.lock]
G --&gt; H[perform_post_install_actions&lt;br/&gt;plugin post_install hook]
&lt;/pre&gt;
&lt;p&gt;对应的 &lt;code&gt;Installer#install!&lt;/code&gt; 片段：&lt;/p&gt;</description></item><item><title>objc4 Autorelease 一页讲透</title><link>https://amatsuzero.github.io/LastStand/posts/ocsourcecodeanalysis/autorelease-explained/</link><pubDate>Mon, 01 Jun 2026 19:50:12 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/ocsourcecodeanalysis/autorelease-explained/</guid><description>&lt;p&gt;objc4 runtime guide&lt;/p&gt;
&lt;h1 id="autorelease-的作用和实现原理"&gt;Autorelease 的作用和实现原理&lt;/h1&gt;
&lt;p&gt;一句话：autorelease 是“延迟一次 release”的机制。对象先被登记到当前线程的自动释放池中， 等池子 pop 时再统一发送 release，从而让返回值和临时对象可以跨过当前语句或当前函数继续存活一小段时间。&lt;/p&gt;
&lt;p&gt;核心文件：runtime/NSObject.mm 数据结构：AutoreleasePoolPage 线程隔离：TLS hot page 边界标记：POOL_BOUNDARY&lt;/p&gt;
&lt;h2 id="先建立正确心智模型"&gt;先建立正确心智模型&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;autorelease pool 不是一堆对象的容器类。&lt;/strong&gt; 在 objc4 里，它更像每个线程私有的一条栈。栈里放两类指针： 普通对象指针，以及表示池边界的 &lt;code&gt;POOL_BOUNDARY&lt;/code&gt;。每次 push 池，就压入一个边界并返回这个边界地址作为 token。 每次 autorelease 对象，就把对象指针压到 hot page 的 &lt;code&gt;next&lt;/code&gt; 位置。pop 时拿 token 找到边界， 把边界之上的对象按后进先出的顺序逐个 &lt;code&gt;objc_release&lt;/code&gt;。&lt;/p&gt;
&lt;h2 id="它解决什么问题"&gt;它解决什么问题&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;**返回 +0 对象：**被调用方可以返回一个“当前调用者可用，但不归调用者拥有”的对象。&lt;/li&gt;
&lt;li&gt;**批量释放临时对象：**循环、事件回调、线程入口可以用池边界控制临时对象峰值。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;兼容手动引用计数：&lt;/strong&gt;&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;**配合 ARC 优化：**运行时和编译器会尝试消除返回值中的多余 retain/autorelease。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="一张图看懂栈变化"&gt;一张图看懂栈变化&lt;/h2&gt;
&lt;p&gt;假设外层池中 autorelease 了 A，又进入内层池 autorelease 了 B、C。内层 pop 只释放 B、C，不影响外层 A。&lt;/p&gt;
&lt;p&gt;push 外层&lt;/p&gt;</description></item><item><title>CocoaPods 源码导读：从命令到依赖求解</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/cocoapods-%E4%BB%8E%E5%91%BD%E4%BB%A4%E5%88%B0%E4%BE%9D%E8%B5%96%E6%B1%82%E8%A7%A3/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/cocoapods-%E4%BB%8E%E5%91%BD%E4%BB%A4%E5%88%B0%E4%BE%9D%E8%B5%96%E6%B1%82%E8%A7%A3/</guid><description>&lt;blockquote&gt;
&lt;p&gt;本文是系列第二篇，基于 CocoaPods 1.16.2 源码。我们从 &lt;code&gt;bin/pod&lt;/code&gt; 进场，走完 CLAide 的命令分发、&lt;code&gt;Podfile&lt;/code&gt; 的 DSL 求值、&lt;code&gt;Analyzer&lt;/code&gt; 的七步分析、&lt;code&gt;Resolver + Molinillo&lt;/code&gt; 的回溯求解，最后交付 &lt;code&gt;AggregateTarget&lt;/code&gt;/&lt;code&gt;PodTarget&lt;/code&gt; 给下一篇讲的下载与集成。&lt;/p&gt;
&lt;p&gt;上一篇：&lt;a href="https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/cocoapods-%E6%9E%B6%E6%9E%84%E6%80%BB%E8%A7%88/"&gt;架构总览&lt;/a&gt; · 下一篇：&lt;a href="https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/cocoapods-%E4%BB%8E%E4%B8%8B%E8%BD%BD%E5%88%B0%E5%B7%A5%E7%A8%8B%E9%9B%86%E6%88%90/"&gt;从下载到工程集成&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;运行示例贯穿全文：&lt;code&gt;pod install --repo-update&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一binpod16-行的入口"&gt;一、&lt;code&gt;bin/pod&lt;/code&gt;：16 行的入口&lt;/h2&gt;
&lt;p&gt;CocoaPods 的可执行文件非常薄，核心逻辑全在 &lt;code&gt;require 'cocoapods'&lt;/code&gt; 之后的 &lt;code&gt;Pod::Command.run&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-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# CocoaPods/bin/pod : 24&lt;/span&gt;
&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; $PROGRAM_NAME &lt;span style="color:#f92672"&gt;==&lt;/span&gt; __FILE__ &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style="color:#f92672"&gt;!&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;ENV&lt;/span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;COCOAPODS_NO_BUNDLER&amp;#39;&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 style="color:#66d9ef"&gt;ENV&lt;/span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;BUNDLE_GEMFILE&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;File&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;expand_path(&lt;span style="color:#e6db74"&gt;&amp;#39;../../Gemfile&amp;#39;&lt;/span&gt;, __FILE__)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; require &lt;span style="color:#e6db74"&gt;&amp;#39;rubygems&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; require &lt;span style="color:#e6db74"&gt;&amp;#39;bundler/setup&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; $LOAD_PATH&lt;span style="color:#f92672"&gt;.&lt;/span&gt;unshift &lt;span style="color:#66d9ef"&gt;File&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;expand_path(&lt;span style="color:#e6db74"&gt;&amp;#39;../../lib&amp;#39;&lt;/span&gt;, __FILE__)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;elsif&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ENV&lt;/span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;COCOAPODS_NO_BUNDLER&amp;#39;&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; require &lt;span style="color:#e6db74"&gt;&amp;#39;rubygems&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; gem &lt;span style="color:#e6db74"&gt;&amp;#39;cocoapods&amp;#39;&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;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;STDOUT&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;sync &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ENV&lt;/span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;CP_STDOUT_SYNC&amp;#39;&lt;/span&gt;&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;TRUE&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;require &lt;span style="color:#e6db74"&gt;&amp;#39;cocoapods&amp;#39;&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;if&lt;/span&gt; profile_filename &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ENV&lt;/span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;COCOAPODS_PROFILE&amp;#39;&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 style="color:#75715e"&gt;# 开 ruby-prof 做性能剖析&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; reporter&lt;span style="color:#f92672"&gt;.&lt;/span&gt;new(&lt;span style="color:#66d9ef"&gt;RubyProf&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;profile { &lt;span style="color:#66d9ef"&gt;Pod&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Command&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;run(&lt;span style="color:#66d9ef"&gt;ARGV&lt;/span&gt;) })&lt;span style="color:#f92672"&gt;.&lt;/span&gt;print(io)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;Pod&lt;/span&gt;&lt;span style="color:#f92672"&gt;::&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;Command&lt;/span&gt;&lt;span style="color:#f92672"&gt;.&lt;/span&gt;run(&lt;span style="color:#66d9ef"&gt;ARGV&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;p&gt;这里有两个工程化细节值得留意：&lt;/p&gt;</description></item><item><title>Objective-C 关联对象 Associated Objects 作用与实现原理</title><link>https://amatsuzero.github.io/LastStand/posts/ocsourcecodeanalysis/associated-objects-explained/</link><pubDate>Mon, 01 Jun 2026 19:50:12 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/ocsourcecodeanalysis/associated-objects-explained/</guid><description>&lt;p&gt;objc4 runtime Associated Objects objc-references.mm&lt;/p&gt;
&lt;h1 id="关联对象-associated-objects-作用与实现原理"&gt;关联对象 Associated Objects 作用与实现原理&lt;/h1&gt;
&lt;p&gt;关联对象让调用方在不改类布局、不新增 ivar 的情况下，把一组 &lt;code&gt;key - value&lt;/code&gt; 挂到任意 Objective-C 对象上。 objc4 的实现不是把字段塞进对象内存，而是用一张运行时全局表保存“对象地址、key、关联值和内存管理策略”的映射。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;入口 API&lt;/strong&gt;&lt;code&gt;objc_setAssociatedObject&lt;/code&gt;&lt;br&gt;
&lt;code&gt;objc_getAssociatedObject&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;核心存储&lt;/strong&gt;&lt;code&gt;AssociationsHashMap&lt;/code&gt;&lt;br&gt;
&lt;code&gt;ObjectAssociationMap&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;值封装&lt;/strong&gt;&lt;code&gt;ObjcAssociation&lt;/code&gt;&lt;br&gt;
&lt;code&gt;policy + value&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;清理时机&lt;/strong&gt;&lt;code&gt;objc_destructInstance&lt;/code&gt;&lt;br&gt;
&lt;code&gt;objc_disposeClassPair&lt;/code&gt;&lt;/p&gt;
&lt;h2 id="目录"&gt;目录&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="#purpose"&gt;作用与使用边界&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#api"&gt;公开 API 与 policy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#storage"&gt;核心结构与字段&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#set-get-remove"&gt;set / get / remove 流程&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#lifetime"&gt;对象销毁与特殊关联&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#forbidden"&gt;禁止关联对象的场景&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#tests"&gt;测试覆盖点&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;a id="purpose"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="作用与使用边界"&gt;作用与使用边界&lt;/h2&gt;
&lt;p&gt;关联对象主要服务于分类、框架扩展、运行时补充状态等场景：调用方只有对象指针和一个稳定 key，就能为对象保存额外值。 这避免了修改类的 ivar 布局，也让分类可以模拟“存储属性”。&lt;/p&gt;
&lt;h3 id="适合做什么"&gt;适合做什么&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;给现有类或分类补充少量状态。&lt;/li&gt;
&lt;li&gt;把辅助对象、回调 block、缓存值挂到宿主对象。&lt;/li&gt;
&lt;li&gt;用唯一地址作为 key，避免和其他调用方冲突。&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;code&gt;objc_removeAssociatedObjects&lt;/code&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;set / get / remove 通过 &lt;code&gt;AssociationsManagerLock&lt;/code&gt; 串行保护表。&lt;/li&gt;
&lt;li&gt;对象析构时可能需要额外释放所有关联值。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;**关键结论：**关联对象是“外置 side table”，不是对象内的 ivar。对象只保存一个“可能有 associated objects”的快速标记，真正的 key/value 在全局表里。&lt;/p&gt;</description></item><item><title>CocoaPods 源码导读：架构总览</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/cocoapods-%E6%9E%B6%E6%9E%84%E6%80%BB%E8%A7%88/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/cocoapods-%E6%9E%B6%E6%9E%84%E6%80%BB%E8%A7%88/</guid><description>&lt;blockquote&gt;
&lt;p&gt;本系列基于 &lt;strong&gt;CocoaPods 1.16.2&lt;/strong&gt;（2026 年 4 月）源码进行分析。源码仓库由 15 个 Ruby Gem 组成，本文先从整体架构与职责拆分讲起，再以 &lt;code&gt;pod install --repo-update&lt;/code&gt; 为主线绘制全景执行图，串起后续两篇专题的切入点。&lt;/p&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;a href="https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/cocoapods-%E4%BB%8E%E5%91%BD%E4%BB%A4%E5%88%B0%E4%BE%9D%E8%B5%96%E6%B1%82%E8%A7%A3/"&gt;从命令到依赖求解&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amatsuzero.github.io/LastStand/posts/interview/ios-source-analysis/cocoapods-%E4%BB%8E%E4%B8%8B%E8%BD%BD%E5%88%B0%E5%B7%A5%E7%A8%8B%E9%9B%86%E6%88%90/"&gt;从下载到工程集成&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一cocoapods-不是单一仓库"&gt;一、CocoaPods 不是单一仓库&lt;/h2&gt;
&lt;p&gt;很多人以为 CocoaPods 就是一个 Ruby 项目，其实官方仓库 &lt;code&gt;CocoaPods/CocoaPods&lt;/code&gt; 只是入口，真正的能力被拆成 15 个独立 gem，每个 gem 只做一件事。用 &lt;code&gt;gem dependency cocoapods&lt;/code&gt; 会看到这样的依赖拓扑：&lt;/p&gt;
&lt;pre class="mermaid"&gt;graph TB
subgraph "入口"
A["bin/pod&lt;br/&gt;(CocoaPods gem)"]
end
subgraph "命令行框架"
B["CLAide&lt;br/&gt;Command/Arg/Option DSL"]
end
subgraph "领域模型"
C["Core&lt;br/&gt;Podfile/Podspec/Source/Lockfile"]
end
subgraph "依赖求解"
D["Molinillo&lt;br/&gt;回溯式 SAT 求解器"]
end
subgraph "下载"
E["cocoapods-downloader&lt;br/&gt;Git/HTTP/SVN/Hg/SCP"]
end
subgraph "Xcode 工程读写"
F["Xcodeproj&lt;br/&gt;pbxproj/xcconfig/workspace"]
G["Nanaimo&lt;br/&gt;ASCII plist 解析"]
end
subgraph "插件与子命令"
H["cocoapods-plugins"]
I["cocoapods-trunk&lt;br/&gt;cocoapods-search&lt;br/&gt;cocoapods-try&lt;br/&gt;cocoapods-deintegrate"]
end
subgraph "辅助"
J["cork&lt;br/&gt;彩色输出"]
K["nap&lt;br/&gt;轻量 HTTP 客户端"]
end
A --&gt; B
A --&gt; C
A --&gt; D
A --&gt; E
A --&gt; F
F --&gt; G
A -.加载.-&gt; H
H -.调用.-&gt; I
A --&gt; J
I --&gt; K
&lt;/pre&gt;
&lt;p&gt;各 gem 的一句话职责：&lt;/p&gt;</description></item><item><title>Objective-C KVC 作用与实现原理</title><link>https://amatsuzero.github.io/LastStand/posts/ocsourcecodeanalysis/kvc-explained/</link><pubDate>Mon, 01 Jun 2026 19:50:12 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/ocsourcecodeanalysis/kvc-explained/</guid><description>&lt;p&gt;Key-Value Coding / Foundation behavior with objc4 runtime support&lt;/p&gt;
&lt;h1 id="objective-c-kvc从字符串-key-到对象读写"&gt;Objective-C KVC：从字符串 key 到对象读写&lt;/h1&gt;
&lt;p&gt;KVC 的核心价值是：把“访问某个属性或实例变量”抽象成 &lt;code&gt;valueForKey:&lt;/code&gt;、&lt;code&gt;setValue:forKey:&lt;/code&gt; 这样的字符串协议。 读完这一页，你应该能说清楚它解决什么问题、Foundation 大致怎样查找成员， 以及 objc4 runtime 在消息发送、元数据查询、ivar 直写和内存管理上提供了哪些支撑。&lt;/p&gt;
&lt;p&gt;适合第一次系统理解 KVC 标注 objc4 / Foundation 边界 含关键流程和注释代码&lt;/p&gt;
&lt;h2 id="目录"&gt;目录&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="#why"&gt;KVC 到底有什么用&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#boundary"&gt;本仓库能看到什么&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#lookup"&gt;读写 key 的查找顺序&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#runtime"&gt;objc4 提供的底层能力&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#classes"&gt;核心类、方法和关键属性&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#flows"&gt;关键操作流程&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#pitfalls"&gt;常见坑与记忆模型&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;a id="why"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="1-kvc-到底有什么用"&gt;1. KVC 到底有什么用&lt;/h2&gt;
&lt;p&gt;平时你写 &lt;code&gt;person.name&lt;/code&gt; 或 &lt;code&gt;[person name]&lt;/code&gt;，访问目标在编译期就固定了。 KVC 允许你在运行时才决定要访问哪个成员：&lt;code&gt;[person valueForKey:@&amp;quot;name&amp;quot;]&lt;/code&gt;。 这使得对象、字典、表单、序列化、绑定和调试工具可以用同一套字符串 key 访问模型对象。&lt;/p&gt;
&lt;h3 id="动态访问"&gt;动态访问&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;运行时才知道字段名&lt;/strong&gt;时，用字符串 key 读取或写入对象。&lt;/p&gt;
&lt;h3 id="统一映射"&gt;统一映射&lt;/h3&gt;
&lt;p&gt;JSON、表单、数据库行、UI 绑定都可以映射到对象属性。&lt;/p&gt;
&lt;h3 id="批量和路径"&gt;批量和路径&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;valueForKeyPath:&lt;/code&gt; 能沿着 &lt;code&gt;department.manager.name&lt;/code&gt; 连续取值。&lt;/p&gt;</description></item><item><title>Objective-C KVO 作用与实现原理</title><link>https://amatsuzero.github.io/LastStand/posts/ocsourcecodeanalysis/kvo-explained/</link><pubDate>Mon, 01 Jun 2026 19:50:12 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/ocsourcecodeanalysis/kvo-explained/</guid><description>&lt;p&gt;objc4 runtime reading note&lt;/p&gt;
&lt;h1 id="kvo从属性变化通知到-runtime-动态子类"&gt;KVO：从“属性变化通知”到 runtime 动态子类&lt;/h1&gt;
&lt;p&gt;KVO（Key-Value Observing）让一个对象在另一个对象的某个 key path 变化时收到回调。 在这个 objc4 仓库里，Foundation 的 KVO 主体代码不在源码中；但 runtime 暴露了 KVO 需要的关键能力： 复制类、切换对象的 isa、判断 ivar 内存语义，并保证这些操作在初始化、弱引用和并发加载场景下安全。&lt;/p&gt;
&lt;p&gt;入口：addObserver 核心：动态子类 通知：will/didChange 底层：objc_duplicateClass&lt;/p&gt;
&lt;p&gt;&lt;a id="what"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="阅读路线"&gt;阅读路线&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="#what"&gt;KVO 解决什么问题&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#principle"&gt;实现原理总览&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#runtime"&gt;objc4 中的关键支撑&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#classes"&gt;核心类和关键方法&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#flows"&gt;关键流程&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#snippets"&gt;带注释代码片段&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#pitfalls"&gt;使用边界和排错&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;a id="principle"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="1-kvo-的作用把状态变化变成可订阅事件"&gt;1. KVO 的作用：把“状态变化”变成可订阅事件&lt;/h2&gt;
&lt;p&gt;普通属性赋值只改变对象内部状态，调用者不知道“谁关心这个变化”。KVO 把某个 key path 的变化包装成标准事件： 被观察对象负责发出变化，观察者在 &lt;code&gt;observeValueForKeyPath:ofObject:change:context:&lt;/code&gt; 中接收。&lt;/p&gt;
&lt;h3 id="解耦"&gt;解耦&lt;/h3&gt;
&lt;p&gt;观察者不需要改写被观察对象的业务代码，只注册感兴趣的 key path。&lt;/p&gt;
&lt;h3 id="统一格式"&gt;统一格式&lt;/h3&gt;
&lt;p&gt;变化以 &lt;code&gt;change&lt;/code&gt; 字典传递，可包含旧值、新值、变化类型等。&lt;/p&gt;
&lt;h3 id="自动拦截"&gt;自动拦截&lt;/h3&gt;
&lt;p&gt;对 KVC/KVO 兼容的 setter，Foundation 可自动在 setter 前后发通知。&lt;/p&gt;
&lt;h3 id="手动通知"&gt;手动通知&lt;/h3&gt;
&lt;p&gt;复杂派生属性或批量变化可用 &lt;code&gt;willChangeValueForKey:&lt;/code&gt; 和 &lt;code&gt;didChangeValueForKey:&lt;/code&gt; 明确包围。&lt;/p&gt;</description></item><item><title>runtime/hashtable2.mm 作用与实现原理</title><link>https://amatsuzero.github.io/LastStand/posts/ocsourcecodeanalysis/hashtable2-explained/</link><pubDate>Mon, 01 Jun 2026 19:50:12 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/ocsourcecodeanalysis/hashtable2-explained/</guid><description>&lt;p&gt;objc4 runtime NXHashTable 集合结构&lt;/p&gt;
&lt;h1 id="runtimehashtable2mm-作用与实现原理"&gt;runtime/hashtable2.mm 作用与实现原理&lt;/h1&gt;
&lt;p&gt;这个文件实现了旧 NeXT/Objective-C runtime 暴露的 &lt;code&gt;NXHashTable&lt;/code&gt;：一个可存放任意指针或整数数据的哈希集合。它不保存 key-value 对；需要映射关系时，runtime 另用 &lt;code&gt;maptable.mm&lt;/code&gt; 的 &lt;code&gt;NXMapTable&lt;/code&gt;。&lt;/p&gt;
&lt;h2 id="一遍读懂"&gt;一遍读懂&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;它用 callback 决定“怎么 hash、怎么判等、怎么释放”。&lt;/li&gt;
&lt;li&gt;每个 bucket 是一条很短的冲突链。&lt;/li&gt;
&lt;li&gt;bucket 中只有 1 个元素时直接存指针，避免额外分配。&lt;/li&gt;
&lt;li&gt;元素数超过 bucket 数时扩容并重算位置。&lt;/li&gt;
&lt;li&gt;删除会把 2 个元素的 bucket 收缩回单指针形态。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="1-它解决什么问题"&gt;1. 它解决什么问题&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;NXHashTable&lt;/code&gt; 是 runtime 内部和兼容 API 使用的通用集合容器。调用者传入一组 &lt;code&gt;NXHashTablePrototype&lt;/code&gt;，告诉表如何处理元素：&lt;code&gt;hash(info, data)&lt;/code&gt; 计算哈希，&lt;code&gt;isEqual(info, a, b)&lt;/code&gt; 判断相等，&lt;code&gt;free(info, data)&lt;/code&gt; 在销毁或 reset 时释放元素。这样同一套表结构可以存指针、字符串，或“结构体首字段作为 key”的对象。&lt;/p&gt;
&lt;p&gt;**关键不变量：**如果两个元素被 &lt;code&gt;isEqual&lt;/code&gt; 判为相等，它们的 &lt;code&gt;hash&lt;/code&gt; 必须一致；而且参与 hash 的内容不能在入表后变化。否则扩容重排后会找不到元素。&lt;/p&gt;
&lt;h2 id="2-数据结构一层数组--小冲突链"&gt;2. 数据结构：一层数组 + 小冲突链&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;NXHashTable&lt;/strong&gt;保存 prototype、元素总数、bucket 数组和可透传给 callback 的 &lt;code&gt;info&lt;/code&gt;。&lt;/p&gt;</description></item><item><title>runtime/maptable.h 作用与实现原理</title><link>https://amatsuzero.github.io/LastStand/posts/ocsourcecodeanalysis/maptable-explained/</link><pubDate>Mon, 01 Jun 2026 19:50:12 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/ocsourcecodeanalysis/maptable-explained/</guid><description>&lt;p&gt;objc4 runtime NXMapTable 开放寻址哈希表 runtime/maptable.h&lt;/p&gt;
&lt;h1 id="runtimemaptableh-作用与实现原理"&gt;runtime/maptable.h 作用与实现原理&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;runtime/maptable.h&lt;/code&gt; 定义了 Objective-C runtime 里旧 NeXT 风格的 &lt;code&gt;NXMapTable&lt;/code&gt;：一个通用的 &lt;strong&gt;key - value 指针映射表&lt;/strong&gt;。 它不拥有业务对象，只负责把指针或整数形式的 key 映射到指针或整数形式的 value， 并通过回调把“怎么 hash、怎么比较、释放时怎么处理”交给调用方决定。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;存储模型&lt;/strong&gt;连续桶数组，每个桶是 &lt;code&gt;{key, value}&lt;/code&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;元素数超过桶数的 75% 后翻倍重哈希。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;runtime 用途&lt;/strong&gt;类名表、协议表、future class 表、少量 meta 到 non-meta 映射。&lt;/p&gt;
&lt;p&gt;&lt;a id="role"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="阅读路径"&gt;阅读路径&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="#role"&gt;它解决什么问题&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#hash-vs-map"&gt;和 hashtable2 的区别&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#shape"&gt;核心数据结构&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#prototype"&gt;Prototype 回调机制&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#algorithm"&gt;查找、插入、删除、扩容流程&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#code"&gt;带注释核心代码&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#runtime-use"&gt;runtime 中的实际使用&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#rules"&gt;必须记住的约束&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;a id="hash-vs-map"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="1-它解决什么问题"&gt;1. 它解决什么问题&lt;/h2&gt;
&lt;p&gt;runtime 需要维护很多“名字到结构体指针”“元类到类”“未来会出现的类名到占位 Class”的映射。 这些映射发生在启动、加载镜像、注册类、查找协议等低层路径上，不能依赖 Objective-C 容器对象。 &lt;code&gt;NXMapTable&lt;/code&gt; 就是一个 C 接口的轻量哈希表。&lt;/p&gt;
&lt;h3 id="它是什么"&gt;它是什么&lt;/h3&gt;
&lt;p&gt;一个 &lt;code&gt;void *&lt;/code&gt; key 到 &lt;code&gt;void *&lt;/code&gt; value 的映射表。key 和 value 可以是指针，也可以把整数强转成指针使用。&lt;/p&gt;</description></item><item><title>Cocos 引擎 iOS 渲染管线深度解析：从 CADisplayLink 到屏幕呈现</title><link>https://amatsuzero.github.io/LastStand/posts/cocosengine-ios-rendering/</link><pubDate>Wed, 08 Jul 2026 19:00:15 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/cocosengine-ios-rendering/</guid><description>&lt;h1 id="cocos-引擎-ios-渲染管线深度解析从-cadisplaylink-到屏幕呈现"&gt;Cocos 引擎 iOS 渲染管线深度解析：从 CADisplayLink 到屏幕呈现&lt;/h1&gt;
&lt;h2 id="引言"&gt;引言&lt;/h2&gt;
&lt;p&gt;在移动端图形开发中，理解渲染管线的底层实现是走向高级工程师的必经之路。Cocos Creator 作为主流的跨平台游戏引擎，其 iOS Metal 后端的渲染实现采用了现代化的 FrameGraph 架构，结合脏状态追踪、资源池化等优化手段，是一份极佳的学习样本。&lt;/p&gt;
&lt;p&gt;本文基于对 Cocos 引擎 &lt;code&gt;gfx-metal&lt;/code&gt; 模块的源码分析，梳理从 &lt;code&gt;CADisplayLink&lt;/code&gt; 帧回调触发到最终 GPU 呈现的完整渲染链路，并深入解读各阶段的关键实现细节。&lt;/p&gt;
&lt;h2 id="整体架构概览"&gt;整体架构概览&lt;/h2&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;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;IOSPlatform&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;IOSPlatform.mm&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;iOS 平台入口，持有 &lt;code&gt;CADisplayLink&lt;/code&gt; 驱动渲染循环&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;RenderPipeline&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;RenderPipeline.cpp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;管线编排器，遍历相机并调度 Flow/Stage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ForwardFlow&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ForwardFlow.cpp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;前向渲染流程，决定渲染策略&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ForwardStage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ForwardStage.cpp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;前向渲染阶段，收集渲染对象并填充 UBO&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;RenderQueue&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;RenderQueue.cpp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;渲染队列，对可渲染对象排序&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;FrameGraph&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;FrameGraph.cpp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;帧图调度器，负责 Pass 编译、排序、合并和执行&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CCMTLDevice&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;MTLDevice.mm&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Metal 设备抽象，管理 Swapchain 和 Queue&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CCMTLSwapchain&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;MTLSwapchain.mm&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;交换链，管理 &lt;code&gt;CAMetalLayer&lt;/code&gt; 和 drawable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CCMTLCommandBuffer&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;MTLCommandBuffer.mm&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;命令缓冲区封装，核心渲染编码入口&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CCMTLRenderCommandEncoder&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;MTLRenderCommandEncoder.h&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;渲染编码器，含脏状态追踪优化&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="完整渲染时序图"&gt;完整渲染时序图&lt;/h2&gt;
&lt;p&gt;以下 Mermaid 时序图展示了从屏幕刷新信号到最终呈现的五个阶段：&lt;/p&gt;</description></item></channel></rss>