应用程序代理访问环境对象

时间:2019-12-17 18:11:25

标签: swift swiftui appdelegate

我在一个类中有一个变量(描述播放的标签),我需要在各个视图之间进行传递,这是通过@EnvironmentObject状态进行的。当更改该标签的函数(与变量在同一类中)被一个视图调用时,该变量将在其他视图中更新。但是,触发通知时,AppDelegate也会调用该函数。目前,我在AppDelegate中获得了包含标签的类,该标签被声明为新实例,这不会导致视图/结构中的变量发生更改。

是否可以授予AppDeleagte对环境对象的访问权限(例如,通过AppDelegate()。environmentobject(myClass),如果可以的话)?还是有更好的方法呢?

简化代码:

包含playlistLabel和用于更改播放列表和标签的函数的类

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)

        }
    }

2 个答案:

答案 0 :(得分:1)

解决此类问题的更好方法,其中需要使同一实例在全局范围内可用,应使用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()可以确保没有其他此类实例再次创建。同样,它将始终显示最新值。

答案 1 :(得分:0)

这是可行的方法。假设您的AppDelegate具有类似

的属性
var musicManager: MusicManager?

在您假设创建SceneDelegate的{​​{1}}中,您可以使用以下代码

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) ... AppDelegate都可以访问HomeView的同一实例。

反之亦然

MusicManager

视情况而定。