AsyncStream 进阶实战:SwiftUI 全局消息流极简实现

基于 Swift 5.9 + 的AsyncStream,实现全局单例、自动生命周期、多点发送单点接收的 SwiftUI 消息流,代码精简且易上手。

一、核心实现:全局流管理器 + SwiftUI 视图

1. 全局消息流管理器(StreamManager)

单例设计,读写分离,并发安全,一行发送消息,极简易用。

Swift 复制代码
import SwiftUI

// 全局单例消息流管理器
final class StreamManager: Sendable {
    static let shared = StreamManager()
    let stream: AsyncStream<String>
    private let continuation: AsyncStream<String>.Continuation
    
    private init() {
        // Swift5.9+ 便捷创建流和续体
        let (stream, continuation) = AsyncStream<String>.makeStream()
        
        // 如果需要背压
        // let (stream, continuation) = AsyncStream<String>.makeStream(bufferingPolicy: .bufferingOldest(10))
        self.stream = stream
        self.continuation = continuation
    }
    
    // 对外暴露的发送方法
    func send(_ message: String) {
        continuation.yield(message)
    }
}

2. SwiftUI 视图集成(ContentView)

自带发送按钮、消息展示,task自动管理监听生命周期,无需手动启停。

Swift 复制代码
struct ContentView: View {
    @State private var messages: [String] = []
    
    var body: some View {
        NavigationStack {
            ScrollView {
                VStack(spacing: 30) {
                    // 发送区+消息展示区
                    VStack(alignment: .leading, spacing: 15) {
                        Text("多点发送 · 单点接收")
                            .font(.headline)
                        
                        // 两个发送者
                        HStack(spacing: 15) {
                            Button("发送者A") {
                                StreamManager.shared.send("客服A:订单已发货")
                            }.buttonStyle(.bordered)
                            
                            Button("发送者B") {
                                StreamManager.shared.send("客服B:感谢咨询")
                            }.buttonStyle(.bordered)
                        }
                        
                        Divider()
                        
                        // 消息展示
                        Text("接收的消息:").font(.caption).foregroundStyle(.secondary)
                        if messages.isEmpty {
                            Text("暂无消息").italic().foregroundStyle(.tertiary)
                        } else {
                            VStack(alignment: .leading, spacing: 8) {
                                ForEach(messages, id: \.self) { msg in
                                    Text(msg)
                                        .padding(8)
                                        .background(Color.blue.opacity(0.1))
                                        .cornerRadius(6)
                                }
                            }
                        }
                    }
                    .padding()
                    .background(Color.gray.opacity(0.1))
                    .cornerRadius(12)
                }
                .padding()
            }
            .navigationTitle("AsyncStream 示例")
            // 自动监听:视图出现启动,消失自动取消
            .task { await listenMessage() }
        }
    }
    
    // 监听流消息
    private func listenMessage() async {
        for await msg in StreamManager.shared.stream {
            messages.append(msg)
        }
    }
}

二、核心亮点(极简核心)

  1. 自动生命周期task修饰符替代手动启停,视图消失自动取消监听,无内存泄漏;
  2. 解耦设计 :发送者仅调用send,接收者仅监听流,互不依赖;
  3. 并发安全 :遵循Sendable,多线程可安全调用发送方法;
  4. 极简 API :Swift5.9+makeStream直接创建流和续体,告别闭包捕获的繁琐写法。

三、快速扩展(按需添加)

1. 自定义消息模型

替换String为自定义模型,适配复杂业务:

Swift 复制代码
// 自定义消息体
struct CustomMsg: Sendable {
    let sender: String
    let content: String
    let time: Date = .now
}
// 管理器中修改泛型:AsyncStream<CustomMsg>
func send(sender: String, content: String) {
    continuation.yield(CustomMsg(sender: sender, content: content))
}

2. 低版本兼容(Swift5.8 及以下)

替换makeStream为闭包写法,兼容 iOS15+/macOS12+:

复制代码
private init() {
    var cont: AsyncStream<String>.Continuation!
    self.stream = AsyncStream { cont = $0 }
    self.continuation = cont
}

3. 消息清空 / 限流

添加简单方法,控制消息数量:

Swift 复制代码
// 管理器中添加清空(或视图中直接操作@State)
func clear() { messages.removeAll() }
// 限流:只保留最近10条
if messages.count >= 10 { messages.removeFirst() }

四、关键注意事项

  1. 适配版本:AsyncStream支持 iOS15+/macOS12+,makeStream支持 iOS17+/Swift5.9+;
  2. UI 更新:task中监听的流,更新@State会自动切主线程,无需手动调度;
  3. 多接收者:一个流可被多个视图同时监听,实现一对多消息分发;
  4. 续体安全:单例模式下续体不会提前释放,非单例需注意持有生命周期。

五、核心总结

AsyncStream替代传统闭包 / 通知 / 代理,实现 SwiftUI 异步消息传递更简洁:

  1. 单例管理器封装流,实现全局消息分发;
  2. task+for await极简监听,自动管理生命周期;
  3. 读写分离,解耦发送者和接收者,代码可维护性拉满。
相关推荐
传奇开心果编程18 分钟前
【SwiftUI入门练中学】第1课 从零开始
学习·ui·ios·swiftui·swift
丿Wayne6 小时前
iOS Token 刷新实战(Actor 避免并发重复刷新)
ios·swift·token·actor·swift并发
终端安全笔记1 天前
iOS 27 给了租赁一个新工具,但它只认受监督的设备
android·网络·安全·ios
大熊猫侯佩1 天前
独立 App 首发完成 iPhone Duo 展开态适配
ios·swiftui·swift
光影少年1 天前
setImmediate 和 setTimeout(0) 的区别
android·前端·react.js·ios·前端框架
2501_916008891 天前
SSE 和 gRPC 流式接口如何抓包,调试 SSE 与 gRPC 流式接口
网络协议·计算机网络·网络安全·ios·adb·https·udp
HouWan2 天前
Flutter: MediaQuery.of(context) 为什么可能拖慢页面?
android·flutter·ios
SoaringHeart2 天前
Swift 进阶&封装:仿 Get 给SwiftUI 添加路由导航能力
swiftui·swift
用户38034165882972 天前
Broadcast Extension 里的 Live Activity:一次跨进程妥协
ios·音视频开发
匠测AI说2 天前
XCUITest 自动化全解:同进程白盒、XCTest 架构、自动同步机制与 iOS 端选型指南
测试工具·ios·自动化