Debugprint 神秘地导致通知触发

问题描述 投票:0回答:1

MRE

struct ContentView: View {
    
    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            Text("SetupMusic").onTapGesture {
                setup()
            }
        }
        .padding()
    }
    
    
    private func setup() {
        debugPrint("Requesting access")
        MPMediaLibrary.requestAuthorization { permission in
            debugPrint("Setting up music player")
            let musicPlayer = MPMusicPlayerController.systemMusicPlayer
            musicPlayer.beginGeneratingPlaybackNotifications()
            debugPrint("Initial State: \(musicPlayer.playbackState)")  //MAGIC LINE!
            NotificationCenter.default.addObserver(forName: .MPMusicPlayerControllerPlaybackStateDidChange, object: musicPlayer, queue: .main) {  notification in
                debugPrint("State changed to \(musicPlayer.playbackState)")
            }
        }
    }
}

将“NSAppleMusicUsageDescription”添加到您的 .plist 文件中,其中包含描述您需要访问媒体播放器框架的原因的字符串值。

  1. 在真实的 iOS 设备上运行应用程序。模拟器不支持MPMediaPlayer 框架。
  2. 点击按钮以允许许可。
  3. 一旦获得授权,您应该获得初始状态。 (停止/暂停)
  4. 转到系统音乐应用程序并在收音机上播放一些内容。
  5. 再次启动应用程序,您应该看到状态更改为“正在播放”
  6. 向下滑动查看通知并暂停音乐,状态将更改为“已暂停”

如果魔线被移除,通知将不会触发。 为什么会这样?

swift nsnotifications mpmusicplayercontroller
1个回答
0
投票

在致电

beginGeneratingPlaybackNotifications
之前,请勿致电
addObserver
。您需要先开始观察,或者创建竞争条件,在开始观察通知之前发出通知。

一般应该尽早拨打

addObserver
,并且一定要均衡地拨打
removeObserver
。否则你可能会得到重复的。要正确执行此操作,如果您创建一个单独的 ViewModel 对象来处理它,则会更容易。如果您尝试在视图内部执行此操作,则很难维护通知取消订阅令牌。但无论如何,
addObserver
必须是第一位。

我不会打赌

requestAuthorization
会在主队列上回调。它不承诺这一点。然而,
debugPrint
会阻止其输出流,因此引入它将对竞争条件产生重大影响,就像您在此处设置的那样。

© www.soinside.com 2019 - 2024. All rights reserved.