You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift 6并发:如何在LogManager初始化时同步调用MainActor隔离方法?

解决方案

要确保系统信息作为第一条日志存入数组,同时不将整个LogManager置于MainActor隔离,推荐采用预占位+异步替换的方式,具体实现如下:

修改后的LogManager代码

@objc
public final class LogManager: NSObject, @unchecked Sendable {
    
    static let sharedInstance = LogManager()
    private var _logs: [String] = []
    private let serialQueue = DispatchQueue(label: "LoggingSerialQueue")
    
    private override init() {
        super.init()
        
        // 先添加占位符,抢占第一条日志的位置
        serialQueue.sync {
            _logs.append("系统信息加载中...")
        }
        
        // 异步在MainActor获取系统信息,再替换占位符
        Task { @MainActor in
            let systemInfo = SysInfo.sysInfo()
            serialQueue.sync {
                // 确保数组非空时替换第一个元素,避免边界问题
                if !_logs.isEmpty {
                    _logs[0] = systemInfo
                } else {
                    _logs.append(systemInfo)
                }
                print("****LogManager**** \(systemInfo)")
            }
        }
    }
    
    func log(_ log: String) {
        serialQueue.sync {
            self._logs.append(log)
            print("****LogManager**** \(log)")
        }
    }
    
    // 可选:提供线程安全的日志读取方法
    var logs: [String] {
        serialQueue.sync { _logs }
    }
}

方案说明

  1. 预占位保证顺序:初始化时先通过串行队列添加占位字符串,后续所有log调用的内容都会排在它之后,从根源上确保系统信息最终是第一条日志。
  2. 异步获取不阻塞:通过Task在MainActor安全获取系统信息,全程不会阻塞LogManager的初始化流程,也不影响多线程调用log的逻辑。
  3. 线程安全延续:所有对_logs数组的操作都通过串行队列同步执行,延续了原代码的线程安全设计,避免多线程竞争问题。

内容的提问来源于stack exchange,提问作者Darren

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 12:02:09