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

SwiftUI中使用@Environment尺寸变量时的无限循环问题

SwiftUI尺寸类环境变量引发ViewModel反复销毁的无限循环问题

问题现象

在SwiftUI视图中引入horizontalSizeClass或verticalSizeClass环境变量后,将设备从竖屏切换为横屏再转回竖屏,会出现以下异常:

  • TestPlayerVM的deinit方法被反复调用,ViewModel不断销毁重建
  • 视图的body陷入无限循环重复执行
  • 移除尺寸类环境引用,或者跳过TestPlayerVM初始化时的addPlayerObservers调用,该问题会消失

问题原因

核心问题在于**PlayerView中用@State修饰TestPlayerVM的错误做法**,结合尺寸类变化触发的视图重建逻辑导致:

  1. 尺寸类变化会触发父视图InfiniteLoopView的body重建,环境变化会传递给子视图PlayerView,引发子视图的状态重置
  2. @State是为值类型设计的状态容器,用于引用类型(Observable对象)时,无法保证实例的生命周期稳定性,视图重建时会重新初始化ViewModel
  3. AVPlayer的订阅(player.publisher)持有ViewModel的引用,与视图重建的逻辑相互作用,形成ViewModel反复创建销毁的循环

解决方案

方案1:改用@StateObject管理ViewModel(推荐)

@StateObject是SwiftUI专门为Observable对象设计的状态容器,能确保ViewModel在视图的整个生命周期内只初始化一次,不会因视图重建而销毁:

struct PlayerView: View {
    @Environment(\.dismiss) var dismiss
    
    var playerURL:URL
    // 将@State替换为@StateObject
    @StateObject var playerVM = TestPlayerVM()
    
    var body: some View {
        VideoPlayer(player: playerVM.player)
            .ignoresSafeArea()
            .background(Color.black)
            .task {
                let playerItem = AVPlayerItem(url: playerURL)
                playerVM.playerItem = playerItem
            }
    }
}

这个修改从根源上解决了ViewModel反复销毁的问题,是SwiftUI中管理Observable对象的标准做法。

方案2:优化订阅避免潜在循环引用(辅助)

如果暂时无法替换@State,可以在订阅时添加weak self避免潜在的循环引用,缓解问题:

private func addPlayerObservers() {
    player.publisher(for: \.timeControlStatus, options: [.initial, .new])
        .receive(on: DispatchQueue.main)
        .sink { [weak self] timeControlStatus in
            guard self != nil else { return }
            print("Player time control status \(timeControlStatus)")
        }
        .store(in: &cancellable)
}

注意:此方法仅为辅助手段,无法彻底解决视图重建导致的ViewModel重置问题,优先使用方案1。

总结

  • 尺寸类变化会触发SwiftUI视图的环境更新与body重计算,必须用正确的状态容器管理引用类型的生命周期
  • @StateObject用于Observable对象的生命周期管理,@State仅适用于值类型
  • 使用AVPlayer等系统框架对象时,确保ViewModel的稳定性是避免资源泄漏和异常行为的关键

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 04:12:05