Xcode 15突发警告:监听系统音量的代码触发跨进程通信提示
解决Xcode 15中监听系统音量的运行时警告问题
问题分析
升级Xcode 15后,原有监听系统音量的代码在初始化@Published var volume时触发运行时警告,而Xcode 14中无此问题。核心原因是:在属性定义阶段直接调用AVAudioSession.sharedInstance().outputVolume时,AVAudioSession尚未完成激活流程,Xcode 15修复了Xcode 14的误判bug后,这类不符合规范的初始化逻辑被正确识别并抛出警告。
修复方案
方案1:延迟初始化初始音量值
不在属性定义时直接赋值,而是在激活AudioSession后再设置初始音量,同时确保在主线程更新@Published属性(SwiftUI要求发布属性的修改必须在主线程执行):
修改后的VolumeObserver代码:
final class VolumeObserver: ObservableObject { @Published var volume: Float = 0.0 // 先设默认占位值 private let session = AVAudioSession.sharedInstance() private var progressObserver: NSKeyValueObservation! func subscribe() { do { try session.setCategory(.ambient) try session.setActive(true, options: .notifyOthersOnDeactivation) // 激活Session后再获取初始音量,切换到主线程更新 DispatchQueue.main.async { self.volume = self.session.outputVolume } } catch { print("cannot activate session") } progressObserver = session.observe(\.outputVolume) { [weak self] (session, _) in guard let self = self else { return } DispatchQueue.main.async { self.volume = session.outputVolume } } } func unsubscribe() { progressObserver.invalidate() // 可选:根据业务需求停用Session do { try session.setActive(false) } catch { print("cannot deactivate session") } } init() { subscribe() } deinit { unsubscribe() // 销毁时自动清理监听资源 } }
方案2:使用惰性初始化
如果希望保留属性的初始赋值逻辑,可以用lazy修饰,确保首次访问volume时,AudioSession已经完成激活:
final class VolumeObserver: ObservableObject { lazy @Published var volume: Float = { AVAudioSession.sharedInstance().outputVolume }() private let session = AVAudioSession.sharedInstance() private var progressObserver: NSKeyValueObservation! func subscribe() { do { try session.setCategory(.ambient) try session.setActive(true, options: .notifyOthersOnDeactivation) } catch { print("cannot activate session") } progressObserver = session.observe(\.outputVolume) { [weak self] (session, _) in guard let self = self else { return } DispatchQueue.main.async { self.volume = session.outputVolume } } } // 其余unsubscribe、init、deinit方法同方案1 }
额外优化点
- 监听闭包中使用
[weak self]避免循环引用,原代码的[self]可能导致内存泄漏 - 在
deinit中调用unsubscribe,确保对象销毁时自动清理监听和Session资源 - 视图中的
onReceive逻辑无需修改,保持原有写法即可
内容的提问来源于stack exchange,提问作者kenada97
相关产品推荐
相关产品推荐

