<?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>iOS 进阶 on Last Stand</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-advanced/</link><description>Recent content in iOS 进阶 on Last Stand</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Sat, 02 May 2026 22:32:27 +0800</lastBuildDate><atom:link href="https://amatsuzero.github.io/LastStand/posts/interview/ios-advanced/index.xml" rel="self" type="application/rss+xml"/><item><title>Instruments详解</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-advanced/instruments%E8%AF%A6%E8%A7%A3/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-advanced/instruments%E8%AF%A6%E8%A7%A3/</guid><description>&lt;p&gt;Instruments 是 Xcode 内置的性能分析套件，基于 DTrace/Apple Trace 基础设施构建，可以对 iOS、iPadOS、macOS、watchOS、tvOS、visionOS 的应用与系统进行 CPU、内存、图形、能耗、网络、I/O 等各个维度的观测。&lt;/p&gt;
&lt;p&gt;Xcode 26（WWDC25）对 Instruments 做了近年来最大规模的升级，重点包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Power Profiler&lt;/strong&gt;：全新的能耗分析工具，支持 Tethered 与 Passive 两种录制模式。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;下一代 SwiftUI instrument&lt;/strong&gt;：基于 Cause &amp;amp; Effect Graph 可视化状态变更到视图更新的因果链。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Processor Trace&lt;/strong&gt;：基于 Apple Silicon 硬件特性的&amp;quot;全量指令级&amp;quot;采集（Xcode 16.3 引入，26 完善）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CPU Counters 重做&lt;/strong&gt;：引入 Bottleneck Analysis 方法论与 CPU Bottlenecks 模板。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Foundation Models instrument&lt;/strong&gt;：为 FoundationModels 框架提供 Prompt / Asset Loading / Inference 分阶段观测。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Animation Hitches 重做&lt;/strong&gt;：修正多显示器场景下的统计，数据量显著减少，处理更快。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;UI 重设计&lt;/strong&gt;：主菜单精简、Settings 页面重写、Track 次级菜单、Launch/Attach 环境变量配置。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="一instruments-基础"&gt;一、Instruments 基础&lt;/h2&gt;
&lt;h3 id="11-启动-instruments-的几种方式"&gt;1.1 启动 Instruments 的几种方式&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;Xcode &lt;code&gt;Product → Profile&lt;/code&gt;（⌘I）&lt;/td&gt;
&lt;td&gt;日常开发，自动以 Release 模式编译并附加符号&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Xcode &lt;code&gt;Debug Navigator&lt;/code&gt; 中的图表&lt;/td&gt;
&lt;td&gt;粗略观测 CPU / Memory / Disk / Network / Energy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;直接打开 &lt;code&gt;Instruments.app&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;对已安装的 App、系统进程或已录制的 &lt;code&gt;.trace&lt;/code&gt; 文件进行分析&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;命令行 &lt;code&gt;xcrun xctrace record&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;CI / 自动化性能回归&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;设备端 Developer Settings 的 Power Profiler&lt;/td&gt;
&lt;td&gt;离线、无 Mac 场景采集能耗数据&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;Xcode 26 中，&lt;code&gt;Product → Profile&lt;/code&gt; 会按默认 scheme 的 Profile 构建配置（通常是 Release + &lt;code&gt;-O&lt;/code&gt;），这与 Debug 模式的数据差异很大，做性能评估时必须用 Profile 构建。&lt;/p&gt;</description></item><item><title>OOP、POP与AOP</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-advanced/oop-pop-aop/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-advanced/oop-pop-aop/</guid><description>&lt;p&gt;在iOS开发中，经常会接触到三种重要的编程范式：面向对象编程（OOP）、面向协议编程（POP）和面向切面编程（AOP）。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="oop---面向对象编程"&gt;OOP - 面向对象编程&lt;/h2&gt;
&lt;h3 id="基本概念"&gt;基本概念&lt;/h3&gt;
&lt;p&gt;面向对象编程（Object-Oriented Programming）是一种以对象为核心的编程范式。它将数据和操作数据的方法封装在一起，形成对象。&lt;/p&gt;
&lt;p&gt;OOP的四大核心特性：&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;iOS中的体现&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;封装&lt;/td&gt;
&lt;td&gt;隐藏内部实现细节，只暴露必要的接口&lt;/td&gt;
&lt;td&gt;&lt;code&gt;@interface&lt;/code&gt;/&lt;code&gt;@implementation&lt;/code&gt;分离，&lt;code&gt;private&lt;/code&gt;属性&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;继承&lt;/td&gt;
&lt;td&gt;子类继承父类的属性和方法&lt;/td&gt;
&lt;td&gt;&lt;code&gt;UIViewController&lt;/code&gt;继承自&lt;code&gt;UIResponder&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;多态&lt;/td&gt;
&lt;td&gt;同一接口可以有不同的实现&lt;/td&gt;
&lt;td&gt;子类重写父类方法&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;抽象&lt;/td&gt;
&lt;td&gt;提取共同特征形成抽象类型&lt;/td&gt;
&lt;td&gt;抽象基类、协议&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="objective-c中的oop"&gt;Objective-C中的OOP&lt;/h3&gt;
&lt;p&gt;Objective-C是一门典型的面向对象语言，它在C语言的基础上添加了面向对象的特性。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-objective-c" data-lang="objective-c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 基类定义
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@interface&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Animal&lt;/span&gt; : &lt;span style="color:#a6e22e"&gt;NSObject&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;@property&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;nonatomic&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;copy&lt;/span&gt;) NSString &lt;span style="color:#f92672"&gt;*&lt;/span&gt;name;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;speak&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;eat:&lt;/span&gt;(NSString &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)food;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;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;@implementation&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Animal&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;speak&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; NSLog(&lt;span style="color:#e6db74"&gt;@&amp;#34;Animal speaks&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;eat:&lt;/span&gt;(NSString &lt;span style="color:#f92672"&gt;*&lt;/span&gt;)food {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; NSLog(&lt;span style="color:#e6db74"&gt;@&amp;#34;%@ is eating %@&amp;#34;&lt;/span&gt;, self.name, food);
&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;@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:#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;@interface&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Dog&lt;/span&gt; : &lt;span style="color:#a6e22e"&gt;Animal&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@property&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;nonatomic&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;copy&lt;/span&gt;) NSString &lt;span style="color:#f92672"&gt;*&lt;/span&gt;breed;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;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;@implementation&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Dog&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 重写父类方法 - 多态
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;speak&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; NSLog(&lt;span style="color:#e6db74"&gt;@&amp;#34;%@ barks: Woof!&amp;#34;&lt;/span&gt;, self.name);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 子类特有方法
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;- (&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt;)&lt;span style="color:#a6e22e"&gt;fetch&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; NSLog(&lt;span style="color:#e6db74"&gt;@&amp;#34;%@ is fetching&amp;#34;&lt;/span&gt;, self.name);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="swift中的oop"&gt;Swift中的OOP&lt;/h3&gt;
&lt;p&gt;Swift同样支持面向对象编程，但提供了更现代的语法和更强的类型安全。&lt;/p&gt;</description></item><item><title>WebView底层原理</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-advanced/webview%E5%BA%95%E5%B1%82%E5%8E%9F%E7%90%86/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-advanced/webview%E5%BA%95%E5%B1%82%E5%8E%9F%E7%90%86/</guid><description>&lt;h2 id="前言"&gt;前言&lt;/h2&gt;
&lt;p&gt;iOS 上的 WebView 目前以 &lt;code&gt;WKWebView&lt;/code&gt; 为事实标准。它对外表现得像一个 &lt;code&gt;UIView&lt;/code&gt; 子类，但内部其实对接着整个 WebKit 引擎——一个由多个独立进程协作的庞大系统。日常开发中遇到的那些困扰：为什么 Web 页白屏不会把 App 带崩？为什么 Cookie 和 App 自身的 &lt;code&gt;NSHTTPCookieStorage&lt;/code&gt; 总是对不上？为什么 JS 调用 Native 永远是异步？为什么 &lt;code&gt;NSURLProtocol&lt;/code&gt; 拦不到 &lt;code&gt;WKWebView&lt;/code&gt; 的请求？这些问题单看 API 都得不到答案，必须下潜到 WebKit 源码里才能看清楚。&lt;/p&gt;
&lt;p&gt;好在 WebKit 是 Apple 官方开源的项目，仓库在 &lt;a href="https://github.com/WebKit/WebKit"&gt;github.com/WebKit/WebKit&lt;/a&gt;。本文基于其 &lt;code&gt;Source/&lt;/code&gt; 目录下的公开源码，按&amp;quot;源码地图 → 多进程架构 → 各进程职责 → 全链路串联 → 工程启示&amp;quot;的顺序，把 &lt;code&gt;WKWebView&lt;/code&gt; 从创建到渲染一帧的底层机制梳理清楚。&lt;/p&gt;
&lt;h2 id="一先看源码地图"&gt;一、先看源码地图&lt;/h2&gt;
&lt;p&gt;阅读源码前，先在脑子里建立目录结构。以 &lt;code&gt;WebKit/WebKit&lt;/code&gt; 仓库的 &lt;code&gt;Source/&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-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Source/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── JavaScriptCore/ # JS 引擎（解释器、JIT 编译器、GC）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── WebCore/ # 渲染引擎核心（DOM、CSSOM、Layout、Paint）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;├── WebKit/ # 多进程框架 + Cocoa 层 API
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── UIProcess/ # 主进程侧（App 进程）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ ├── API/Cocoa/ # WKWebView.mm、WKProcessPool.mm 等
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ ├── API/ios/ # WKWebViewIOS.mm
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ │ ├── ios/ # WKContentView.mm、WebPageProxyIOS.mm
&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;│ ├── WebProcess/ # 渲染进程侧（WebContent）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── NetworkProcess/ # 独立网络进程
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ ├── GPUProcess/ # 独立 GPU 进程
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;│ └── Shared/ # 跨进程共享的数据结构、IPC 消息定义
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;└── WTF/ # 基础容器、线程、字符串工具库
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;日常 iOS 开发能看到的 &lt;code&gt;WKWebView&lt;/code&gt;，对应的实现就在 &lt;code&gt;Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm&lt;/code&gt;。它是一个 Objective-C++ 文件，内部只是持有一个 C++ 的 &lt;code&gt;WebPageProxy&lt;/code&gt; 对象，几乎所有实际工作都转发给它。为什么要这样设计？原因就藏在下一节要讲的多进程架构里。&lt;/p&gt;</description></item><item><title>WebView离线包</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-advanced/webview%E7%A6%BB%E7%BA%BF%E5%8C%85/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-advanced/webview%E7%A6%BB%E7%BA%BF%E5%8C%85/</guid><description>&lt;h2 id="背景"&gt;背景&lt;/h2&gt;
&lt;p&gt;Hybrid 开发模式下，WebView 加载 H5 页面的体验一直是痛点。一个典型的 H5 页面加载流程涉及：初始化 WebView -&amp;gt; DNS 解析 -&amp;gt; 建立连接 -&amp;gt; 下载 HTML -&amp;gt; 解析 HTML -&amp;gt; 下载 CSS/JS/图片 -&amp;gt; 渲染页面。在弱网或首次加载场景下，白屏时间常常达到 2~5 秒，远不如 Native 体验。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;离线包&lt;/strong&gt;的核心思路是：将 H5 的静态资源（HTML、CSS、JS、图片、字体等）预先打包下发到客户端本地，WebView 加载时直接从本地读取资源，跳过网络请求环节，从而大幅缩短页面加载时间。&lt;/p&gt;
&lt;h2 id="离线包加载-vs-在线加载"&gt;离线包加载 vs 在线加载&lt;/h2&gt;
&lt;pre class="mermaid"&gt;sequenceDiagram
participant App
participant WebView
participant Local as 本地离线包
participant Server as 远程服务器
Note over App, Server: 在线加载流程
App-&gt;&gt;WebView: loadURL
WebView-&gt;&gt;Server: DNS + TCP + TLS + HTTP请求
Server--&gt;&gt;WebView: HTML
WebView-&gt;&gt;Server: 请求 CSS/JS/图片
Server--&gt;&gt;WebView: 资源文件
WebView-&gt;&gt;WebView: 渲染页面
Note over App, Server: 离线包加载流程
App-&gt;&gt;WebView: loadURL（被拦截）
WebView-&gt;&gt;Local: 读取本地 HTML
Local--&gt;&gt;WebView: HTML
WebView-&gt;&gt;Local: 读取本地 CSS/JS/图片
Local--&gt;&gt;WebView: 资源文件
WebView-&gt;&gt;WebView: 渲染页面
&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;对比项&lt;/th&gt;
&lt;th&gt;在线加载&lt;/th&gt;
&lt;th&gt;离线包加载&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;首屏时间&lt;/td&gt;
&lt;td&gt;2~5秒（弱网更久）&lt;/td&gt;
&lt;td&gt;0.5~1秒&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;网络依赖&lt;/td&gt;
&lt;td&gt;强依赖&lt;/td&gt;
&lt;td&gt;仅更新时需要网络&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;白屏问题&lt;/td&gt;
&lt;td&gt;严重&lt;/td&gt;
&lt;td&gt;基本消除&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;资源新鲜度&lt;/td&gt;
&lt;td&gt;实时最新&lt;/td&gt;
&lt;td&gt;有一定延迟&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;流量消耗&lt;/td&gt;
&lt;td&gt;每次访问都消耗&lt;/td&gt;
&lt;td&gt;仅增量更新消耗&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="整体架构"&gt;整体架构&lt;/h2&gt;
&lt;p&gt;一个完整的离线包系统包含三大部分：&lt;/p&gt;</description></item><item><title>iOS国际化</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-advanced/ios%E5%9B%BD%E9%99%85%E5%8C%96/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-advanced/ios%E5%9B%BD%E9%99%85%E5%8C%96/</guid><description>&lt;h2 id="前言"&gt;前言&lt;/h2&gt;
&lt;p&gt;很多团队对&amp;quot;国际化&amp;quot;的理解停留在&amp;quot;把中文文案翻译成英文&amp;quot;，等真正把 App 推向多区域时就会发现远远不够：阿拉伯语用户看到的界面左右颠倒了，用户在纽约和东京看到的&amp;quot;今天&amp;quot;不是同一天，欧洲的小数点变成了逗号，日本用户抱怨价格里的¥符号指向人民币而不是日元，印度用户发现自己的 ₹1,23,456.78 被错误地按千分位显示成 ₹123,456.78，复数规则在俄语里比英语复杂得多，而这些问题单靠&amp;quot;翻译&amp;quot;都解决不了。&lt;/p&gt;
&lt;p&gt;国际化（Internationalization，简称 i18n，取首末字母与中间 18 个字符）是&lt;strong&gt;架构层面的能力建设&lt;/strong&gt;，让 App 能够适配不同语言、地区、文字方向、日历、时区、货币、单位制与文化习俗；而本地化（Localization，l10n）是针对某个具体地区的&amp;quot;适配落地&amp;quot;。两者的关系是：&amp;ldquo;国际化一次，本地化 N 次&amp;rdquo;。&lt;/p&gt;
&lt;p&gt;本文从 &lt;code&gt;NSLocale&lt;/code&gt;/&lt;code&gt;Locale&lt;/code&gt; 的基础模型开始，把 iOS 国际化的完整工程面梳理清楚——文案本地化、复数/性别规则、RTL 布局、多时区、多币种、单位与数字格式、图片资源、字体、App 内切换语言、测试方法，最后给出研发规范与排查清单。&lt;/p&gt;
&lt;h2 id="一基础概念localelanguage-与-region"&gt;一、基础概念：Locale、Language 与 Region&lt;/h2&gt;
&lt;h3 id="11-locale-不等于-language"&gt;1.1 Locale 不等于 Language&lt;/h3&gt;
&lt;p&gt;大多数工程师第一次接触国际化时会把&amp;quot;语言&amp;quot;和&amp;quot;地区&amp;quot;混为一谈，这在 iOS 下会直接导致格式错误。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Language（语言）&lt;/strong&gt;：&lt;code&gt;zh&lt;/code&gt;、&lt;code&gt;en&lt;/code&gt;、&lt;code&gt;ar&lt;/code&gt;、&lt;code&gt;ja&lt;/code&gt;…决定 UI 文字内容。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Region（地区）&lt;/strong&gt;：&lt;code&gt;CN&lt;/code&gt;、&lt;code&gt;US&lt;/code&gt;、&lt;code&gt;SA&lt;/code&gt;、&lt;code&gt;JP&lt;/code&gt;…决定格式（日期、数字、货币、时间制 12/24h、起始星期、度量单位）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Locale（语言+地区）&lt;/strong&gt;：两者合成一个完整的标识，如 &lt;code&gt;zh_CN&lt;/code&gt;、&lt;code&gt;en_US&lt;/code&gt;、&lt;code&gt;ar_SA&lt;/code&gt;、&lt;code&gt;en_IN&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;一个美国人移居日本后，完全可能把 iPhone 语言设为英文，但地区设为日本。此时：&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;UI 文案&lt;/td&gt;
&lt;td&gt;英文&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;日期格式&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1月23日(月)&lt;/code&gt; 风格？No，应显示 &lt;code&gt;January 23 (Mon)&lt;/code&gt;，因为语言决定月/星期的&lt;strong&gt;名字&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;数字分隔符&lt;/td&gt;
&lt;td&gt;&lt;code&gt;,&lt;/code&gt; 作千分位（与日本/美国一致）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;货币符号&lt;/td&gt;
&lt;td&gt;&lt;code&gt;¥&lt;/code&gt;（JPY）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;温度单位&lt;/td&gt;
&lt;td&gt;&lt;code&gt;℃&lt;/code&gt;（日本）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;首日周&lt;/td&gt;
&lt;td&gt;周日（日本区域）&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;对应的 &lt;code&gt;Locale&lt;/code&gt; 是 &lt;code&gt;en_JP&lt;/code&gt;——看似奇怪，但在现实中非常普遍。代码里要区分&amp;quot;用哪个语言去查字符串&amp;quot;和&amp;quot;用哪个 Locale 去格式化数据&amp;quot;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; preferredLanguage = Locale.preferredLanguages.first ?? &lt;span style="color:#e6db74"&gt;&amp;#34;en&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; currentLocale = Locale.current
&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;let&lt;/span&gt; formatter = DateFormatter()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;formatter.locale = currentLocale
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;formatter.dateStyle = .long
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;print(formatter.string(from: Date()))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;不要传 &lt;code&gt;Locale(identifier: &amp;quot;en&amp;quot;)&lt;/code&gt; 去格式化数字，那会丢掉用户的区域偏好。&lt;/p&gt;</description></item><item><title>iOS无障碍树详解</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-advanced/ios%E6%97%A0%E9%9A%9C%E7%A2%8D%E6%A0%91/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-advanced/ios%E6%97%A0%E9%9A%9C%E7%A2%8D%E6%A0%91/</guid><description>&lt;h2 id="前言"&gt;前言&lt;/h2&gt;
&lt;p&gt;打开 iPhone 的&amp;quot;设置 → 辅助功能 → 旁白（VoiceOver）&amp;quot;，再用三指在屏幕上滑动，iPhone 就会逐个读出当前界面上的每个控件：&lt;code&gt;&amp;quot;登录按钮，双击以激活&amp;quot;&lt;/code&gt;、&lt;code&gt;&amp;quot;用户名，文本框，已填写 ancheng&amp;quot;&lt;/code&gt;、&lt;code&gt;&amp;quot;价格，¥99&amp;quot;&lt;/code&gt;。这背后支撑 VoiceOver、开关控制（Switch Control）、语音控制（Voice Control）、全键盘访问（Full Keyboard Access）、Xcode UITest、AI Agent 识屏 等一系列能力的，是一棵并行于 &lt;code&gt;UIView&lt;/code&gt; 视图树的 &lt;strong&gt;无障碍树（Accessibility Tree，AX Tree）&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;对大多数 iOS 工程师来说，无障碍树是&amp;quot;黑盒&amp;quot;：设了 &lt;code&gt;isAccessibilityElement = true&lt;/code&gt;、填了 &lt;code&gt;accessibilityLabel&lt;/code&gt;，然后就不管了。但一旦遇到以下问题，就不得不深入理解它的工作机制：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;为什么 UITest 里用 &lt;code&gt;XCUIElement&lt;/code&gt; 定位不到某个按钮？&lt;/li&gt;
&lt;li&gt;为什么打开 VoiceOver 后 App 明显变卡？&lt;/li&gt;
&lt;li&gt;为什么一个自绘的 &lt;code&gt;CALayer&lt;/code&gt; 按钮在 VoiceOver 下无法被朗读？&lt;/li&gt;
&lt;li&gt;为什么 &lt;code&gt;UILabel&lt;/code&gt; 嵌在 &lt;code&gt;UIStackView&lt;/code&gt; 里焦点顺序是乱的？&lt;/li&gt;
&lt;li&gt;SwiftUI 的 &lt;code&gt;.accessibilityElement(children: .combine)&lt;/code&gt; 到底合并了什么？&lt;/li&gt;
&lt;li&gt;Accessibility Inspector 里看到的树结构从哪儿来？&lt;/li&gt;
&lt;li&gt;AI Agent（如 iOS 上的 Claude、ChatGPT Mac 客户端）是如何&amp;quot;看到&amp;quot;屏幕的？&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;本文从&lt;strong&gt;操作系统层的 AX 架构&lt;/strong&gt;讲起，逐层拆解：AX Server 守护进程、UIKit 中的 &lt;code&gt;UIAccessibility&lt;/code&gt; 协议、&lt;code&gt;UIAccessibilityElement&lt;/code&gt; 类、&lt;code&gt;UIAccessibilityContainer&lt;/code&gt; 协议、焦点排序算法、SwiftUI 的 AX 实现、辅助技术的工作原理、性能优化、UITest 与 AI 识屏原理、调试工具与最佳实践。&lt;/p&gt;</description></item><item><title>iOS音视频原理</title><link>https://amatsuzero.github.io/LastStand/posts/interview/ios-advanced/%E9%9F%B3%E8%A7%86%E9%A2%91%E5%8E%9F%E7%90%86/</link><pubDate>Sat, 02 May 2026 22:32:27 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/interview/ios-advanced/%E9%9F%B3%E8%A7%86%E9%A2%91%E5%8E%9F%E7%90%86/</guid><description>&lt;p&gt;音视频开发是iOS中一个庞大且核心的技术领域，涵盖采集、编码、传输、解码、渲染等完整链路。本文从基础概念出发，深入iOS平台提供的音视频框架和底层原理。&lt;/p&gt;
&lt;h2 id="音视频处理全链路"&gt;音视频处理全链路&lt;/h2&gt;
&lt;p&gt;一个完整的音视频系统（如直播、视频通话、短视频）包含以下环节：&lt;/p&gt;
&lt;pre class="mermaid"&gt;flowchart LR
A["采集&lt;br/&gt;Camera/Mic"] --&gt; B["前处理&lt;br/&gt;美颜/降噪"]
B --&gt; C["编码&lt;br/&gt;H.264/AAC"]
C --&gt; D["封装&lt;br/&gt;FLV/MP4"]
D --&gt; E["传输&lt;br/&gt;RTMP/HLS"]
E --&gt; F["解封装&lt;br/&gt;解析容器"]
F --&gt; G["解码&lt;br/&gt;VideoToolbox"]
G --&gt; H["后处理&lt;br/&gt;滤镜/混音"]
H --&gt; I["渲染&lt;br/&gt;Metal/Speaker"]
&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;环节&lt;/th&gt;
&lt;th&gt;做什么&lt;/th&gt;
&lt;th&gt;iOS中对应的技术&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;采集&lt;/td&gt;
&lt;td&gt;从摄像头/麦克风获取原始数据&lt;/td&gt;
&lt;td&gt;AVCaptureSession&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;前处理&lt;/td&gt;
&lt;td&gt;美颜、滤镜、降噪、回声消除&lt;/td&gt;
&lt;td&gt;CoreImage、vDSP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;编码&lt;/td&gt;
&lt;td&gt;将原始数据压缩为体积更小的格式&lt;/td&gt;
&lt;td&gt;VideoToolbox、AudioToolbox&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;封装&lt;/td&gt;
&lt;td&gt;将编码后的音视频数据打包到容器中&lt;/td&gt;
&lt;td&gt;AVAssetWriter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;传输&lt;/td&gt;
&lt;td&gt;通过网络发送到服务器或其他端&lt;/td&gt;
&lt;td&gt;URLSession、第三方推流SDK&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;解封装&lt;/td&gt;
&lt;td&gt;从容器中分离出音频流和视频流&lt;/td&gt;
&lt;td&gt;AVAssetReader&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;解码&lt;/td&gt;
&lt;td&gt;将压缩数据还原为原始像素/采样数据&lt;/td&gt;
&lt;td&gt;VideoToolbox、AudioToolbox&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;后处理&lt;/td&gt;
&lt;td&gt;滤镜、水印、混音等&lt;/td&gt;
&lt;td&gt;CoreImage、Metal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;渲染&lt;/td&gt;
&lt;td&gt;将画面显示到屏幕、声音输出到扬声器&lt;/td&gt;
&lt;td&gt;AVSampleBufferDisplayLayer、Metal、AudioUnit&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="核心术语"&gt;核心术语&lt;/h2&gt;
&lt;p&gt;在深入细节之前，先了解几个贯穿全文的核心概念：&lt;/p&gt;
&lt;h3 id="什么是编解码器codec"&gt;什么是编解码器（Codec）&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Codec&lt;/strong&gt; = Coder + Decoder，即编码器+解码器的合称。编码器负责将原始音视频数据压缩为更小的格式，解码器负责将压缩数据还原。&lt;/p&gt;
&lt;p&gt;音视频中有两类完全不同的&amp;quot;格式&amp;quot;概念，初学者极易混淆：&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;编码格式（Codec）：定义数据怎么压缩
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 视频：H.264、H.265、VP9、AV1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 音频：AAC、MP3、Opus、FLAC
&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;封装格式（Container）：定义压缩后的数据怎么组织存储
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; MP4、MOV、FLV、MKV、TS
&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; MP4容器 + H.264视频 + AAC音频 （最常见的组合）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; MOV容器 + H.265视频 + AAC音频 （iPhone录制默认）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; FLV容器 + H.264视频 + AAC音频 （直播推流常用）
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; MKV容器 + AV1视频 + Opus音频 （新一代免费组合）
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="什么是h264和h265"&gt;什么是H.264和H.265&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;H.264&lt;/strong&gt;（也叫AVC，Advanced Video Coding）是目前使用最广泛的视频编码标准，由ITU-T和ISO/IEC联合制定，2003年发布。它定义了一套将视频帧压缩为比特流的算法规范——包括如何划分图像块、如何预测、如何变换量化等。几乎所有设备和平台都支持H.264硬件解码。&lt;/p&gt;</description></item></channel></rss>