实用指南:iOS Swift 线程开发指南
<style>pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace !important; font-size: 14px !important; line-height: 1.6 !important; padding: 16px !important; margin: 16px 0 !important; background-color: rgba(248, 248, 248, 1) !important; border: 1px solid rgba(225, 228, 232, 1) !important; border-radius: 6px !important; tab-size: 4 !important; -moz-tab-size: 4 !important; max-width: 100% !important; box-sizing: border-box !important }code { font-family: "Consolas", "Monaco", "Courier New", monospace !important; font-size: 14px !important; white-space: pre !important; word-wrap: normal !important; word-break: normal !important; overflow-wrap: normal !important; display: inline !important; background: rgba(0, 0, 0, 0) !important; border: none !important; padding: 0 !important; margin: 0 !important; line-height: inherit !important }
pre code { background: rgba(0, 0, 0, 0) !important; border: 0 !important; border-radius: 0 !important; display: block !important; line-height: 1.6 !important; margin: 0 !important; max-width: none !important; overflow: visible !important; padding: 0 !important; white-space: pre !important; word-wrap: normal !important; word-break: normal !important; color: inherit !important }
.token.comment, .token.prolog, .token.doctype, .token.cdata { color: rgba(112, 128, 144, 1) !important; font-style: italic !important }
.token.punctuation { color: rgba(153, 153, 153, 1) !important }
.token.atrule, .token.attr-value, .token.keyword { color: rgba(0, 119, 170, 1) !important; font-weight: bold !important }
.token.function, .token.class-name { color: rgba(221, 74, 104, 1) !important; font-weight: bold !important }
.token.selector, .token.attr-name, .token.string, .token.char, .token.builtin, .token.inserted { color: rgba(102, 153, 0, 1) !important }
.token.property, .token.tag, .token.boolean, .token.number, .token.constant, .token.symbol, .token.deleted { color: rgba(153, 0, 85, 1) !important }
.cnblogs-markdown pre, .cnblogs-post-body pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; background-color: rgba(248, 248, 248, 1) !important; border: 1px solid rgba(225, 228, 232, 1) !important; border-radius: 6px !important; padding: 16px !important; margin: 16px 0 !important }
pre, pre, pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important }</style>
<div class="markdown_views prism-atom-one-dark" id="content_views"><svg style="display: none" xmlns="http://www.w3.org/2000/svg"><path d="M5,0 0,2.5 5,5z" id="raphael-marker-block" stroke-linecap="round" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0)"></path></svg><h2>iOS Swift 线程开发指南</h2><h3>1、线程介绍Thread</h3><p>线程是操作系统进行任务调度的基本执行单元,负责承载应用程序中各类任务的运行。</p><p>iOS 应用主要涉及两种线程:<strong>主线程(Main Thread)</strong> 和<strong>子线程</strong>,它们各司其职,共同保障应用的流畅与稳定。</p><h5>1.1、主线程(Main Thread)</h5><p>主线程是APP启动时由系统自动创建的第一个线程,也称为 UI 线程。</p><blockquote><p><strong>主要特点:</strong><br>
1、App 启动时自动创建(无需开发者创建)<br>
2、唯一的 UI 线程<br>
3、驱动整个应用运行</p></blockquote><blockquote><p><strong>主要职责:</strong><br>
1、所有和界面相关的操作:UI渲染、更新、展示…<br>
2、所有和用户交互的操作:点击、滑动、手势识别…</p></blockquote><p>注意:<strong>禁止在主线程执行任何耗时操作,会影响用户体验。</strong><br>
原因:主线程运行在一个叫做 RunLoop 的循环中,这个循环负责:</p><blockquote><p>1、处理用户交互(触摸、点击等)<br>
2、更新 UI 界面<br>
3、执行系统事件</p></blockquote><p>如果主线程执行了耗时操作,RunLoop 就会被阻塞,导致上述所有操作都无法及时处理。<br>
从而会导致:</p><blockquote><p>1、屏幕刷新率下降(低于 60Hz)<br>
2、动画变得卡顿或不流畅<br>
3、触摸事件无法及时响应<br>
4、应用看起来像"死机"了一样</p></blockquote><p>更严重的是,iOS 系统还有一个 watchdog 计时器(看门狗机制):</p><blockquote><p>watchdog 主要监控场景和超时时间(不同系统版本中,时间规定会略有差异):<br>
1、应用启动必须在限定时间内完成(应用启动必须在限定时间内完成)<br>
冷启动:20 秒<br>
热启动:10-15 秒<br>
.<br>
2、主线程被阻塞的最长时间(主线程被阻塞的最长时间)<br>
普通操作:5-10 秒<br>
特殊场景:可能更短<br>
.<br>
3、后台任务超时(应用进入后台后的执行时间)<br>
iOS 12 及之前:约 5 分钟<br>
iOS 13 及之后:约 30 秒</p></blockquote><p><em><font color="red">如果主线程无响应5-10 秒,应用会被强制终止或者系统弹出警告:“App无响应”。</font></em> 此时在在 Xcode 控制台可能看到日志:</p>
<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code class="prism language-swift"><span class="token builtin">Exception</span> <span class="token keyword">Type</span><span class="token punctuation">:</span> <span class="token constant">EXC_CRASH</span> <span class="token punctuation">(</span><span class="token constant">SIGKILL</span><span class="token punctuation">)</span>
<span class="token builtin">Exception</span> <span class="token builtin">Codes</span><span class="token punctuation">:</span> <span class="token number">0x0000000000000000</span><span class="token punctuation">,</span> <span class="token number">0x0000000000000000</span>
<span class="token builtin">Exception</span> <span class="token builtin">Note</span><span class="token punctuation">:</span> <span class="token constant">EXC_CORPSE_NOTIFY</span>
<span class="token builtin">Termination</span> <span class="token builtin">Reason</span><span class="token punctuation">:</span> <span class="token builtin">Namespace</span> <span class="token constant">SPRINGBOARD</span><span class="token punctuation">,</span> <span class="token builtin">Code</span> <span class="token number">0x8badf00d</span>
注意:<span class="token number">0x8badf00d</span> 这个错误代码就是 <span class="token string">"ate bad food"</span> 的谐音,专门表示 <span class="token builtin">Watchdog</span> 超时</code></pre>
<h5>1.2、子线程</h5><p>子线程是用来辅助主线程的,专门帮主线程处理“它不擅长”的任务,让主线程UI处理得更高效。</p><blockquote><p><strong>主要特点:</strong><br>
1、子线程是由开发者主动创建的,与主线程共享应用内存空间。<br>
2、子线程数量,理论上无硬性上限,但是受设备内存和 CPU 制约,数量不宜过多,通常活跃线程数在 个为宜。</p></blockquote><blockquote><p><strong>主要职责,处理耗时工作:</strong><br>
1、网络请求:所有 API 调用、数据下载。<br>
2、文件 I/O:大文件读写、数据库操作。<br>
3、数据处理:图片解码/处理、视频压缩、复杂计算。<br>
4、其他耗时操作:任何可能导致主线程卡顿的任务。</p></blockquote><h5>1.3、iOS 线程的精髓</h5><p>我们开发时,核心目标是“<strong>让主线程保持 60FPS 的流畅渲染,给用户最丝滑的体验</strong>”。大家主要记住这三条,就掌握了 iOS 线程的精髓</p><blockquote><p>1、主线程 = 展示层 - 只负责 UI 显示和用户交互<br>
2、子线程 = 工作层 - 处理所有可能耗时的任务<br>
3、线程间通信 - 子线程数据处理完成后,可通过 <strong>@MainActor</strong> 或 <strong>DispatchQueue.main.async</strong> 等桥接机制,将结果安全传递至主线程进行 UI 更新。</p></blockquote><p><font color="gray">不仅iOS客户端,安卓、鸿蒙客户端其实也是类似的(虽然鸿蒙子线程设计的不够现代化,但思想上是一致的)。</font></p><p>不知道大家是否认同呢?欢迎在评论区分享您的见解哈。</p><h3>2、 Swift 中子线程并发方案选择</h3><p>Swift中实现子线程并发的可选方案如下:</p><blockquote><p>1、Swift 并发 (Task) - ⭐️⭐️⭐️⭐️⭐️ 首选<br>
2、GCD (Grand Central Dispatch) - ⭐️⭐️⭐️⭐️ 备选<br>
3、OperationQueue - ⭐️⭐️⭐️ 特定场景<br>
4、Thread - ⭐️⭐️ 不推荐<br>
5、其他:pthread、NSThread、 std::thread等OC的实现 - ⭐️ 不考虑</p></blockquote><h5>2.1、Swift 并发 (Task)</h5><p>Swift Task 是 Apple 推出的现代化、结构化并发解决方案,它通过 async/await 语法和 Actor 模型,在编译器层面保证了并发代码的安全性和可维护性,彻底改变了 iOS/macOS 平台的异步编程范式。</p><blockquote><p><strong>思维转变:</strong><br>
1、传统线程思维:“我要创建线程,管理线程,同步线程” (关注的是执行机制)<br>
2、Swift Task 思维:“我要完成什么工作,需要什么数据”(关注的是业务目标)<br>
错误认知:Task 会取代线程<br>
正确认知:Task 在线程之上提供了更高级的抽象</p></blockquote><blockquote><p><strong>Task与线程关系比喻:</strong><br>
线程 = 工厂的机器设备(物理资源)<br>
Task = 生产订单(逻辑任务)<br>
系统 = 智能调度员(自动分配订单到合适设备)<br>
一个线程可以执行多个 Task,一个 Task 也可能在多个线程中执行(挂起和恢复时)。</p></blockquote><p>相较于传统的线程管理,Task解决了哪些问题?</p><blockquote><p>1、资源浪费问题:<br>
线程是重量级资源,创建慢且占用大量内存,等待时还会阻塞浪费CPU。<br>
而Task内存占用极轻,能在少量线程上切换运行,等待时主动挂起释放资源,实现CPU与内存的高效利用。<br>
.<br>
2、"回调地狱"问题<br>
传统回调导致代码嵌套层层加深,形成难以维护的“回调地狱”,错误处理也分散各处。<br>
Task 通过 async/await 语法,将异步代码转为线性书写,使逻辑清晰、错误处理集中,彻底摆脱回调嵌套。<br>
.<br>
3、数据竞争问题<br>
传统线程需手动加锁防数据竞争,问题难发现、难调试。<br>
Task 的 Actor 模型由编译器自动保护共享数据,从根源杜绝竞争。<br>
.<br>
4、生命周期管理问题<br>
传统线程需手动管理,易泄漏且取消困难。<br>
Task 结构化并发支持自动级联取消,资源管理自动化。<br>
.<br>
5、优先级和调度问题<br>
传统线程手动管理优先级,易出调度问题。<br>
Task 系统自动调度,智能处理优先级与负载,开发者只需标注重要性。</p></blockquote><p><strong>Swift Task线程自动管理:</strong><br>
Swift 运行时为每个应用进程维护了一个全局线程池。当我们创建 Task 时,任务会被智能调度器自动分配到线程池中的空闲线程上执行。任务完成后,线程立即释放回池中复用,从而高效管理并发并避免线程创建销毁的开销。</p><h5>2.2、GCD (Grand Central Dispatch)</h5><p>GCD (Grand Central Dispatch) 是苹果开发的底层并发框架,基于线程池模型,通过队列管理任务执行。</p><blockquote><p><strong>核心特点:</strong><br>
1、队列管理 - 提供了串行队列、并发队列、主队列<br>
2、自动线程管理 - 系统全局线程池,自动复用线程(与Swift Task线程池非同一个)<br>
3、优先级系统 - 不同QoS级别管理任务优先级<br>
4、C语言基础 - 轻量级、接近系统底层</p></blockquote><p>GCD 是基于线程池的底层并发框架,通过队列管理、操作线程,适合简单的后台任务和UI调度。对于复杂异步流程和新项目,Swift Task 在性能、安全性和开发体验上全面优于 GCD,GCD仅建议用于维护旧代码(兼容老旧代码库、或者C/Objective-C项目)或简单场景。</p><h5>2.3、OperationQueue</h5><p>OperationQueue 是基于 GCD 的高级抽象,它在 GCD 之上添加了面向对象的任务管理能力。</p><blockquote><p><strong>相比 GCD 的优势:</strong><br>
1、任务依赖:可明确设置操作间的执行顺序依赖关系<br>
2、状态管理:可查询操作状态(准备中、执行中、完成、取消)<br>
3、精确控制:可取消单个操作或挂起整个队列<br>
4、最大并发数:精确控制同时执行的操作数量<br>
5、Completion Block:每个操作支持完成回调</p></blockquote><p>OperationQueue相比Swift Task存在明显局限:API冗长,需创建特定对象封装任务;存在额外性能开销;语法陈旧,无法使用现代async/await简洁语法;仍需手动处理内存管理问题。这些不足使其在现代Swift并发编程中竞争力不足。</p><h5>2.4、Thread线程</h5><p>Thread 是 iOS/macOS 平台最基础的并发实现,它直接封装了底层的 POSIX 线程,为开发者提供了面向对象的线程管理接口。</p><p>Thread作为最底层线程方案,由开发者自行管理维护线程对象。存在资源消耗大、创建销毁成本高、上下文切换昂贵、同步调试困难、缺乏任务抽象和取消机制等核心问题。</p><p>在现代并发编程中已被更高效的GCD和Swift Task全面取代。</p><h5>2.5、Swift并发方案建议</h5><p>✅ 在 Swift 项目中,<strong>应首选使用 Swift 并发</strong>处理所有异步任务和 UI 更新。<br>
⚠️ <strong>GCD</strong> 仅用于与传统 API 交互或特定性能优化场景。<br>
⚠️ <strong>OperationQueue</strong> 适用于需要精细控制任务依赖关系的复杂工作流。<br>
⚠️ <strong>Thread</strong> 因抽象层级过低,除系统级底层开发外应彻底弃用。</p><h3>3、Swift 并发功能介绍</h3><h5>3.1、Swift 并发模型的核心功能</h5><blockquote><p>1、async/await<br>
异步函数:用 async 标记,表示函数内部可以“暂停”等待。<br>
等待结果:用 await 调用异步函数,此时当前任务会挂起,不阻塞线程,直到结果就绪。<br>
.<br>
2、Task<br>
工作单元:代表一项可以在后台执行的异步任务。<br>
入口点:它是从同步世界进入异步世界的起点。<br>
.<br>
3、结构化并发<br>
父子关系:任务可以拥有子任务,形成清晰的层级结构。<br>
自动管理:父任务会自动等待所有子任务完成,并且取消操作会自动传递给所有子任务,防止任务“失控”。<br>
.<br>
4、Actor<br>
数据保镖:一种引用类型,专门用于在并发环境中安全地管理共享数据。<br>
串行访问:它确保在任何时刻,只有一个任务能访问其内部数据,从而从根本上防止数据竞争。<br>
.<br>
5、@MainActor<br>
主线程调度员:一个特殊的Actor,它确保所有标记给它的代码(尤其是UI更新)都在主线程上安全执行。</p></blockquote><h5>3.2、主线程中执行任务</h5><p>在主线程中使用 Task 的主要意义是:</p><blockquote><p>1、在异步上下文中安全地更新 UI<br>
2、确保某些操作必须在主线程执行<br>
3、避免线程竞争条件</p></blockquote><p>在同步方法中调用异步方法 - 必须用 Task:</p>
<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code class="prism language-swift"><span class="token comment">// 同步方法中调用异步方法必须用 Task</span>
<span class="token keyword">func</span> <span class="token function">syncFunction</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// ❌ 错误:不能在同步函数中直接调用异步函数</span>
<span class="token comment">// await fetchData()</span>
<span class="token comment">// ✅ 正确:必须用 Task 包装</span>
<span class="token builtin">Task</span> <span class="token punctuation">{</span>
await <span class="token function">fetchData</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>在 SwiftUI 中调用异步方法:</p>
<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code class="prism language-swift"><span class="token keyword">struct</span> <span class="token builtin">ContentView</span><span class="token punctuation">:</span> <span class="token builtin">View</span> <span class="token punctuation">{</span>
<span class="token keyword">var</span> body<span class="token punctuation">:</span> some <span class="token builtin">View</span> <span class="token punctuation">{</span>
<span class="token function">Button</span><span class="token punctuation">(</span><span class="token string">"加载数据"</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// ✅ SwiftUI 的 action 闭包中需要 Task</span>
<span class="token builtin">Task</span> <span class="token punctuation">{</span>
await <span class="token function">loadData</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token comment">// .task 修饰符会自动处理</span>
<span class="token keyword">var</span> body2<span class="token punctuation">:</span> some <span class="token builtin">View</span> <span class="token punctuation">{</span>
<span class="token function">List</span><span class="token punctuation">(</span>items<span class="token punctuation">,</span> id<span class="token punctuation">:</span> \<span class="token punctuation">.</span>id<span class="token punctuation">)</span> <span class="token punctuation">{</span> item <span class="token keyword">in</span>
<span class="token function">Text</span><span class="token punctuation">(</span>item<span class="token punctuation">.</span>name<span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token punctuation">.</span>task <span class="token punctuation">{</span>
<span class="token comment">// ✅ 不需要显式 Task,框架自动处理</span>
await <span class="token function">loadData</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>多个 Task 的执行特点:</p>
<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code class="prism language-swift"><span class="token comment">// 示例:创建多个独立的 Task</span>
<span class="token builtin">Task</span> <span class="token punctuation">{</span> @<span class="token builtin">MainActor</span> <span class="token keyword">in</span>
<span class="token function">print</span><span class="token punctuation">(</span><span class="token string">"Task 1 开始 - 线程:"</span><span class="token punctuation">,</span> <span class="token builtin">Thread</span><span class="token punctuation">.</span>current<span class="token punctuation">)</span>
<span class="token keyword">self</span><span class="token punctuation">.</span>label<span class="token punctuation">.</span>text <span class="token operator">=</span> <span class="token string">"任务1"</span>
<span class="token punctuation">}</span>
<span class="token builtin">Task</span> <span class="token punctuation">{</span> @<span class="token builtin">MainActor</span> <span class="token keyword">in</span>
<span class="token function">print</span><span class="token punctuation">(</span><span class="token string">"Task 2 开始 - 线程:"</span><span class="token punctuation">,</span> <span class="token builtin">Thread</span><span class="token punctuation">.</span>current<span class="token punctuation">)</span>
<span class="token keyword">self</span><span class="token punctuation">.</span>button<span class="token punctuation">.</span>isEnabled <span class="token operator">=</span> <span class="token boolean">false</span>
<span class="token punctuation">}</span>
<span class="token builtin">Task</span> <span class="token punctuation">{</span> @<span class="token builtin">MainActor</span> <span class="token keyword">in</span>
<span class="token function">print</span><span class="token punctuation">(</span><span class="token string">"Task 3 开始 - 线程:"</span><span class="token punctuation">,</span> <span class="token builtin">Thread</span><span class="token punctuation">.</span>current<span class="token punctuation">)</span>
<span class="token keyword">self</span><span class="token punctuation">.</span>indicator<span class="token punctuation">.</span><span class="token function">stopAnimating</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token comment">// 执行结果:</span>
<span class="token comment">// Task 1 开始 - 线程: <NSThread: 0x...>{number = 1, name = main}</span>
<span class="token comment">// Task 2 开始 - 线程: <NSThread: 0x...>{number = 1, name = main}</span>
<span class="token comment">// Task 3 开始 - 线程: <NSThread: 0x...>{number = 1, name = main}</span>
<span class="token comment">// 所有 Task 都在主线程执行,但执行顺序不确定!</span></code></pre>
<p>避免阻塞主线程案例:</p>
<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code class="prism language-swift"><span class="token keyword">class</span> <span class="token class-name">ResponsiveUIExample</span> <span class="token punctuation">{</span>
<span class="token comment">// ❌ 阻塞主线程的做法</span>
<span class="token keyword">func</span> <span class="token function">blockingOperation</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// 如果在主线程执行耗时操作会卡住 UI</span>
<span class="token function">performHeavyCalculation</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// 如果这个函数是同步的,会阻塞主线程</span>
<span class="token punctuation">}</span>
<span class="token comment">// ✅ 使用 Task 保持 UI 响应性</span>
<span class="token keyword">func</span> <span class="token function">nonBlockingOperation</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token builtin">Task</span> <span class="token punctuation">{</span>
<span class="token comment">// 1. 立即响应用户操作</span>
await <span class="token function">showProgressFeedback</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment">// 2. 在后台执行耗时操作</span>
<span class="token keyword">let</span> result <span class="token operator">=</span> await <span class="token function">performHeavyCalculationAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment">// 3. 回到主线程显示结果</span>
await <span class="token function">displayResult</span><span class="token punctuation">(</span>result<span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token comment">// UI 保持响应,用户可以继续交互</span>
<span class="token punctuation">}</span>
@<span class="token builtin">MainActor</span>
<span class="token keyword">private</span> <span class="token keyword">func</span> <span class="token function">showProgressFeedback</span><span class="token punctuation">(</span><span class="token punctuation">)</span> async <span class="token punctuation">{</span>
<span class="token comment">// 显示加载状态</span>
<span class="token punctuation">}</span>
<span class="token keyword">private</span> <span class="token keyword">func</span> <span class="token function">performHeavyCalculationAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span> async <span class="token operator">-</span><span class="token operator">></span> <span class="token builtin">String</span> <span class="token punctuation">{</span>
<span class="token comment">// 在后台线程执行繁重计算</span>
<span class="token keyword">return</span> await <span class="token builtin">Task</span><span class="token punctuation">.</span>detached <span class="token punctuation">{</span>
<span class="token function">print</span><span class="token punctuation">(</span><span class="token string">"繁重计算在线程: <span class="token interpolation"><span class="token delimiter variable">\(</span><span class="token builtin">Thread</span><span class="token punctuation">.</span>current<span class="token delimiter variable">)</span></span>"</span><span class="token punctuation">)</span>
<span class="token comment">// 模拟复杂计算</span>
<span class="token builtin">Thread</span><span class="token punctuation">.</span><span class="token function">sleep</span><span class="token punctuation">(</span>forTimeInterval<span class="token punctuation">:</span> <span class="token number">3</span><span class="token punctuation">)</span>
<span class="token keyword">return</span> <span class="token string">"计算结果"</span>
<span class="token punctuation">}</span><span class="token punctuation">.</span>value
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<h5>3.3、子线程中执行任务</h5>
<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code class="prism language-swift"><span class="token keyword">class</span> <span class="token class-name">BackgroundExample</span> <span class="token punctuation">{</span>
<span class="token keyword">func</span> <span class="token function">runInBackground</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token builtin">Task</span><span class="token punctuation">.</span>detached <span class="token punctuation">{</span>
<span class="token comment">//detached 切换到后台子线程执行任务</span>
<span class="token function">print</span><span class="token punctuation">(</span><span class="token string">"后台线程: <span class="token interpolation"><span class="token delimiter variable">\(</span><span class="token builtin">Thread</span><span class="token punctuation">.</span>current<span class="token delimiter variable">)</span></span>"</span><span class="token punctuation">)</span>
await <span class="token keyword">self</span><span class="token punctuation">.</span><span class="token function">heavyWork</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">private</span> <span class="token keyword">func</span> <span class="token function">heavyWork</span><span class="token punctuation">(</span><span class="token punctuation">)</span> async <span class="token punctuation">{</span>
<span class="token function">print</span><span class="token punctuation">(</span><span class="token string">"繁重任务执行中"</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<h5>3.4、子线程切换主线程方式</h5><p>有两种主流切换方式:</p><blockquote><p>1、MainActor.run:最直接的线程切换方式<br>
2、@MainActor:自动确保函数在主线程执行</p></blockquote><p>使用 Task 和 @MainActor:</p>
<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code class="prism language-swift"><span class="token comment">// 在后台线程执行,然后切换回主线程</span>
<span class="token builtin">Task</span> <span class="token punctuation">{</span>
<span class="token comment">// 在后台线程执行耗时操作</span>
<span class="token keyword">let</span> result <span class="token operator">=</span> await <span class="token function">someHeavyWork</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment">// 自动切换回主线程更新 UI</span>
await <span class="token builtin">MainActor</span><span class="token punctuation">.</span>run <span class="token punctuation">{</span>
label<span class="token punctuation">.</span>text <span class="token operator">=</span> result
<span class="token comment">// 这里已经在主线程了</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>使用 @MainActor 属性包装器:</p>
<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code class="prism language-swift">@<span class="token builtin">MainActor</span>
<span class="token keyword">func</span> <span class="token function">updateUI</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// 这个函数会自动在主线程执行</span>
label<span class="token punctuation">.</span>text <span class="token operator">=</span> <span class="token string">"Hello"</span>
button<span class="token punctuation">.</span>isEnabled <span class="token operator">=</span> <span class="token boolean">true</span>
<span class="token punctuation">}</span>
<span class="token builtin">Task</span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> data <span class="token operator">=</span> await <span class="token function">fetchData</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
await <span class="token function">updateUI</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// 自动切换到主线程</span>
<span class="token punctuation">}</span></code></pre>
<h5>3.5、并发执行任务</h5>
<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code class="prism language-swift"><span class="token builtin">Task</span> <span class="token punctuation">{</span>
<span class="token comment">// 使用 async let 并发执行多个异步操作</span>
async <span class="token keyword">let</span> user <span class="token operator">=</span> <span class="token function">fetchUser</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// 启动用户数据获取,不等待</span>
async <span class="token keyword">let</span> posts <span class="token operator">=</span> <span class="token function">fetchPosts</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// 启动文章数据获取,不等待</span>
<span class="token comment">// 等待两个任务都完成</span>
<span class="token keyword">let</span> <span class="token punctuation">(</span>userData<span class="token punctuation">,</span> postData<span class="token punctuation">)</span> <span class="token operator">=</span> await <span class="token punctuation">(</span>user<span class="token punctuation">,</span> posts<span class="token punctuation">)</span>
<span class="token function">print</span><span class="token punctuation">(</span><span class="token string">"并发完成: <span class="token interpolation"><span class="token delimiter variable">\(</span>userData<span class="token delimiter variable">)</span></span>, <span class="token interpolation"><span class="token delimiter variable">\(</span>postData<span class="token punctuation">.</span><span class="token builtin">count</span><span class="token delimiter variable">)</span></span>篇文章"</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token keyword">func</span> <span class="token function">fetchUser</span><span class="token punctuation">(</span><span class="token punctuation">)</span> async <span class="token operator">-</span><span class="token operator">></span> <span class="token builtin">String</span> <span class="token punctuation">{</span>
<span class="token keyword">try</span><span class="token operator">?</span> await <span class="token builtin">Task</span><span class="token punctuation">.</span><span class="token function">sleep</span><span class="token punctuation">(</span>nanoseconds<span class="token punctuation">:</span> <span class="token number">2_000_000_000</span><span class="token punctuation">)</span> <span class="token comment">// 模拟2秒请求</span>
<span class="token keyword">return</span> <span class="token string">"用户信息"</span>
<span class="token punctuation">}</span>
<span class="token keyword">func</span> <span class="token function">fetchPosts</span><span class="token punctuation">(</span><span class="token punctuation">)</span> async <span class="token operator">-</span><span class="token operator">></span> <span class="token punctuation">[</span><span class="token builtin">String</span><span class="token punctuation">]</span> <span class="token punctuation">{</span>
<span class="token keyword">try</span><span class="token operator">?</span> await <span class="token builtin">Task</span><span class="token punctuation">.</span><span class="token function">sleep</span><span class="token punctuation">(</span>nanoseconds<span class="token punctuation">:</span> <span class="token number">1_000_000_000</span><span class="token punctuation">)</span> <span class="token comment">// 模拟1秒请求</span>
<span class="token keyword">return</span> <span class="token punctuation">[</span><span class="token string">"文章1"</span><span class="token punctuation">,</span> <span class="token string">"文章2"</span><span class="token punctuation">]</span>
<span class="token punctuation">}</span></code></pre>
<h5>3.6、任务组并发</h5>
<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code class="prism language-swift"><span class="token builtin">Task</span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> total <span class="token operator">=</span> await <span class="token function">withTaskGroup</span><span class="token punctuation">(</span>of<span class="token punctuation">:</span> <span class="token builtin">Int</span><span class="token punctuation">.</span><span class="token keyword">self</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> group <span class="token keyword">in</span>
<span class="token comment">// 添加3个并发任务</span>
<span class="token keyword">for</span> i <span class="token keyword">in</span> <span class="token number">1</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token number">3</span> <span class="token punctuation">{</span>
group<span class="token punctuation">.</span>addTask <span class="token punctuation">{</span>
<span class="token keyword">return</span> await <span class="token keyword">self</span><span class="token punctuation">.</span><span class="token function">processItem</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span> <span class="token comment">// 每个任务处理一个项目</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">var</span> sum <span class="token operator">=</span> <span class="token number">0</span>
<span class="token keyword">for</span> await result <span class="token keyword">in</span> group <span class="token punctuation">{</span> <span class="token comment">// 按完成顺序收集结果</span>
sum <span class="token operator">+</span><span class="token operator">=</span> result <span class="token comment">// 累加每个任务的结果</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> sum
<span class="token punctuation">}</span>
<span class="token function">print</span><span class="token punctuation">(</span><span class="token string">"任务组总和: <span class="token interpolation"><span class="token delimiter variable">\(</span>total<span class="token delimiter variable">)</span></span>"</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token keyword">func</span> <span class="token function">processItem</span><span class="token punctuation">(</span><span class="token number">_</span> id<span class="token punctuation">:</span> <span class="token builtin">Int</span><span class="token punctuation">)</span> async <span class="token operator">-</span><span class="token operator">></span> <span class="token builtin">Int</span> <span class="token punctuation">{</span>
<span class="token keyword">try</span><span class="token operator">?</span> await <span class="token builtin">Task</span><span class="token punctuation">.</span><span class="token function">sleep</span><span class="token punctuation">(</span>nanoseconds<span class="token punctuation">:</span> <span class="token number">500_000_000</span><span class="token punctuation">)</span> <span class="token comment">// 模拟处理时间</span>
<span class="token keyword">return</span> id <span class="token operator">*</span> <span class="token number">10</span> <span class="token comment">// 返回处理后的值</span>
<span class="token punctuation">}</span></code></pre>
<h5>3.7、顺序执行</h5>
<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code class="prism language-swift"><span class="token builtin">Task</span> <span class="token punctuation">{</span>
<span class="token comment">// 异步代码必须在 Task 中执行</span>
<span class="token keyword">let</span> step1 <span class="token operator">=</span> await <span class="token function">downloadData</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// 等待第一步完成</span>
<span class="token keyword">let</span> step2 <span class="token operator">=</span> await <span class="token function">processData</span><span class="token punctuation">(</span>step1<span class="token punctuation">)</span> <span class="token comment">// 用第一步结果执行第二步</span>
<span class="token keyword">let</span> step3 <span class="token operator">=</span> await <span class="token function">saveData</span><span class="token punctuation">(</span>step2<span class="token punctuation">)</span> <span class="token comment">// 用第二步结果执行第三步</span>
<span class="token function">print</span><span class="token punctuation">(</span><span class="token string">"顺序执行完成: <span class="token interpolation"><span class="token delimiter variable">\(</span>step3<span class="token delimiter variable">)</span></span>"</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token keyword">func</span> <span class="token function">downloadData</span><span class="token punctuation">(</span><span class="token punctuation">)</span> async <span class="token operator">-</span><span class="token operator">></span> <span class="token builtin">String</span> <span class="token punctuation">{</span>
<span class="token string">"原始数据"</span> <span class="token comment">// 模拟下载</span>
<span class="token punctuation">}</span>
<span class="token keyword">func</span> <span class="token function">processData</span><span class="token punctuation">(</span><span class="token number">_</span> data<span class="token punctuation">:</span> <span class="token builtin">String</span><span class="token punctuation">)</span> async <span class="token operator">-</span><span class="token operator">></span> <span class="token builtin">String</span> <span class="token punctuation">{</span>
<span class="token string">"处理后的: <span class="token interpolation"><span class="token delimiter variable">\(</span>data<span class="token delimiter variable">)</span></span>"</span> <span class="token comment">// 模拟数据处理</span>
<span class="token punctuation">}</span>
<span class="token keyword">func</span> <span class="token function">saveData</span><span class="token punctuation">(</span><span class="token number">_</span> data<span class="token punctuation">:</span> <span class="token builtin">String</span><span class="token punctuation">)</span> async <span class="token operator">-</span><span class="token operator">></span> <span class="token builtin">String</span> <span class="token punctuation">{</span>
<span class="token string">"已保存: <span class="token interpolation"><span class="token delimiter variable">\(</span>data<span class="token delimiter variable">)</span></span>"</span> <span class="token comment">// 模拟数据保存</span>
<span class="token punctuation">}</span></code></pre>
<h5>3.8、任务取消</h5>
<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code class="prism language-swift"><span class="token keyword">let</span> task <span class="token operator">=</span> <span class="token builtin">Task</span> <span class="token punctuation">{</span>
<span class="token keyword">for</span> i <span class="token keyword">in</span> <span class="token number">1</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token number">5</span> <span class="token punctuation">{</span>
<span class="token keyword">try</span> <span class="token builtin">Task</span><span class="token punctuation">.</span><span class="token function">checkCancellation</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// 检查任务是否被取消</span>
<span class="token function">print</span><span class="token punctuation">(</span><span class="token string">"任务进度: <span class="token interpolation"><span class="token delimiter variable">\(</span>i<span class="token delimiter variable">)</span></span>"</span><span class="token punctuation">)</span>
<span class="token keyword">try</span> await <span class="token builtin">Task</span><span class="token punctuation">.</span><span class="token function">sleep</span><span class="token punctuation">(</span>nanoseconds<span class="token punctuation">:</span> <span class="token number">1_000_000_000</span><span class="token punctuation">)</span> <span class="token comment">// 等待1秒</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> <span class="token string">"任务完成"</span>
<span class="token punctuation">}</span>
<span class="token comment">// 2秒后取消任务</span>
<span class="token builtin">Task</span> <span class="token punctuation">{</span>
<span class="token keyword">try</span> await <span class="token builtin">Task</span><span class="token punctuation">.</span><span class="token function">sleep</span><span class="token punctuation">(</span>nanoseconds<span class="token punctuation">:</span> <span class="token number">2_000_000_000</span><span class="token punctuation">)</span>
task<span class="token punctuation">.</span><span class="token function">cancel</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// 取消任务</span>
<span class="token function">print</span><span class="token punctuation">(</span><span class="token string">"任务已取消"</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span></code></pre>
<h5>3.9、线程安全 Actor</h5>
<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code class="prism language-swift">actor <span class="token builtin">SafeCounter</span> <span class="token punctuation">{</span>
<span class="token keyword">private</span> <span class="token keyword">var</span> <span class="token builtin">count</span> <span class="token operator">=</span> <span class="token number">0</span> <span class="token comment">// 私有状态,受到actor保护</span>
<span class="token keyword">func</span> <span class="token function">increment</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token builtin">count</span> <span class="token operator">+</span><span class="token operator">=</span> <span class="token number">1</span> <span class="token comment">// 安全修改,不会数据竞争</span>
<span class="token punctuation">}</span>
<span class="token keyword">func</span> <span class="token function">getValue</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">></span> <span class="token builtin">Int</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token builtin">count</span> <span class="token comment">// 安全读取</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">let</span> counter <span class="token operator">=</span> <span class="token function">SafeCounter</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token builtin">Task</span> <span class="token punctuation">{</span>
await <span class="token function">withTaskGroup</span><span class="token punctuation">(</span>of<span class="token punctuation">:</span> <span class="token builtin">Void</span><span class="token punctuation">.</span><span class="token keyword">self</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> group <span class="token keyword">in</span>
<span class="token keyword">for</span> <span class="token number">_</span> <span class="token keyword">in</span> <span class="token number">1</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token number">100</span> <span class="token punctuation">{</span>
group<span class="token punctuation">.</span>addTask <span class="token punctuation">{</span>
await counter<span class="token punctuation">.</span><span class="token function">increment</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// 安全并发访问</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">let</span> <span class="token keyword">final</span> <span class="token operator">=</span> await counter<span class="token punctuation">.</span><span class="token function">getValue</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token function">print</span><span class="token punctuation">(</span><span class="token string">"最终计数: <span class="token interpolation"><span class="token delimiter variable">\(</span><span class="token keyword">final</span><span class="token delimiter variable">)</span></span>"</span><span class="token punctuation">)</span> <span class="token comment">// 保证是100</span>
<span class="token punctuation">}</span></code></pre>
<h5>3.10、优先级控制</h5>
<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code class="prism language-swift"><span class="token keyword">let</span> highPriorityTask <span class="token operator">=</span> <span class="token function">Task</span><span class="token punctuation">(</span>priority<span class="token punctuation">:</span> <span class="token punctuation">.</span>high<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">print</span><span class="token punctuation">(</span><span class="token string">"高优先级任务执行"</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token keyword">let</span> lowPriorityTask <span class="token operator">=</span> <span class="token function">Task</span><span class="token punctuation">(</span>priority<span class="token punctuation">:</span> <span class="token punctuation">.</span>low<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">print</span><span class="token punctuation">(</span><span class="token string">"低优先级任务执行"</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token comment">// 系统会优先调度高优先级任务</span></code></pre>
</div><br><br>
来源:https://www.cnblogs.com/ljbguanli/p/19556020
頁:
[1]