App Delegate 访问环境对象

App Delegate Accessing Environment Object

我在 class 中有一个变量(描述戏剧的标签),我需要在我的视图之间传递它,这是我通过 @EnvironmentObject 状态完成的。当更改该标签的函数(与变量在同一 class 中)被一个视图调用时,该变量将在其他视图中更新。但是,当触发通知时,AppDelegate 也会调用该函数。目前,我已经得到 class 包含在 AppDelegate 中声明为新实例的标签,这导致 view/struct.

中的变量没有变化

是否可以让 AppDeleagte 访问环境对象(例如,通过 AppDelegate().environmentobject(myClass),如果可以,在哪里?)或者有更好的方法吗?

简化代码:

Class 其中包含播放列表标签和更改播放列表和标签的函数

class MusicManager: NSObject, ObservableObject {

    var playlistLabel: String = ""

    func playPlaylistNow(chosenPlaylist: String?) {  
        playlistLabel = "Playlist: \(chosenPlaylist!)"
    }

}

显示标签的主页视图

struct HomeView: View {

    @EnvironmentObject var musicManager: MusicManager

    var body: some View {

        Text(musicManager.playlistLabel)

    }

}

AppDelegate

class AppDelegate: UIResponder, UIApplicationDelegate, AVAudioPlayerDelegate {

    var musicManager: MusicManager = MusicManager()

        func application(_ application: UIApplication, didReceive notification: UILocalNotification) {
            var playlistName: String = ""
            if let userInfo = notification.userInfo {
                playlistName = userInfo["soundName"] as! String
            }
            musicPlayerManager.playPlaylist(chosenPlaylist: playlistName)

        }
    }

这是可能的方法。假设您的AppDelegate有属性喜欢

var musicManager: MusicManager?

在你的 SceneDelegate 中,我想你创建 HomeView,你可以有以下代码

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {

    let musicManager = MusicManager()
    if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
        addDelegate.musicManager = musicManager
    }
    let contentView = HomeView().environmentObject(musicManager)
    ...

因此 AppDelegateHomeView 都可以访问 MusicManager.

的相同实例

反之亦然

...
var musicManager: MusicManager?
if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
    musicManager = addDelegate.musicManager
}
let contentView = HomeView().environmentObject(musicManager ?? MusicManager())
...

取决于哪个更可取。

解决此类问题的更好方法,其中您需要使同一实例全局可用,您应该使用 Singleton 设计模式。此外,根据最佳编码实践,我们应该避免使用多个职责和变量重载 AppDelegate。通过划分责任来解耦你的代码总是更好的。

class MusicManager: NSObject, ObservableObject {
   let sharedMusicManager = MusicManager()
   var playlistLabel: String = ""

   private init() {}

  func playPlaylistNow(chosenPlaylist: String?) {  
    playlistLabel = "Playlist: \(chosenPlaylist!)"
  }
}

AppDelegate

 class AppDelegate: UIResponder, UIApplicationDelegate, AVAudioPlayerDelegate {

     func application(_ application: UIApplication, didReceive notification: UILocalNotification) {
        var playlistName: String = ""
        if let userInfo = notification.userInfo {
            playlistName = userInfo["soundName"] as! String
        }
        sharedMusicManager.playPlaylist(chosenPlaylist: playlistName)
    }
}

同样,您可以从其他视图更新变量。保留 private init() 将确保不会再创建该 class 的其他实例。此外,它将始终显示最新的值。