首页 > 解决方案 > 如何在swiftui中使两个具有可观察对象协议的类相互访问

问题描述

我有 2 个类,它们都符合可观察对象。MusicController,它充当创建的每个音乐对象的模型的一部分。当应用程序进入不同的状态(willEnterForeground)并相应地响应 UI 时,MusicCheck 充当 UI 的通知器。

我试图让两个类都能够相互访问。我将它们都设置为 EnvironmentObject,但这不允许它们在应用程序崩溃时相互访问,因为 MusicController 无权访问用于 MusicCheck 的 EnvironmentObject。

当音乐开始播放(在音乐控制器中)时,我想在 MusicCheck 中运行一个函数来更改变量值。如何允许 MusicController 类访问 MusicCheck 类?

class MusicController: ObservableObject {
@EnvironmentObject var musicCheck: MusicCheck
@Published var isPlaying = false

init() {
 // play the music and setup other sound logic

// Change the variable in MusicCheck
}
}



class MusicCheck: ObservableObject {
@Published var isPlayingAfter = false

init() {
  // perform logic for when the application willEnterForeground
}
}

标签: swiftxcodeswiftui

解决方案


这是一个选项,onAppear用于传递对 的引用musicCheck

class MusicController: ObservableObject {
    @Published var isPlaying = false
    var musicCheck : MusicCheck?
    
    func setup(musicCheck : MusicCheck) {
        self.musicCheck = musicCheck
        
        //perform other setup logic
    }
}

class MusicCheck: ObservableObject {
    @Published var isPlayingAfter = false
    
    init() {
        // perform logic for when the application willEnterForeground
    }
}

struct ContentView : View {
    @StateObject private var musicCheck = MusicCheck()
    @StateObject private var musicController = MusicController()
    
    var body: some View {
        VStack {
            Text("Hello, world")
        }.onAppear {
            musicController.setup(musicCheck: musicCheck)
        }
    }
}

另一种可能性是使用单例模式。我对这种方法持谨慎态度,因为它可能导致难以测试的情况。另外,我经常看到的一个错误是人们创建了一个非单例实例并且对为什么他们有多个副本感到困惑——我使用 aprivate init来避免这种情况。

class MusicController: ObservableObject {
    @Published var isPlaying = false
    
    init() {
        MusicCheck.shared.someFunction()
    }
}

class MusicCheck: ObservableObject {
    static var shared = MusicCheck()
    
    @Published var isPlayingAfter = false
    
    private init() {
        // perform logic for when the application willEnterForeground
    }
    
    func someFunction() {
        
    }
}

struct ContentView : View {
    @StateObject private var musicCheck = MusicCheck.shared
    @StateObject private var musicController = MusicController()
    
    var body: some View {
        VStack {
            Text("Hello, world")
        }
    }
}

推荐阅读