2

我有一个音频应用程序并实现了 CarPlay,我已按照本指南添加 CarPlay 支持:https ://blog.fethica.com/add-carplay-support-to-swiftradio/#

该应用程序使用 com.apple.developer.playable-content 权利和媒体播放器框架,据我所知,这是在 iOS 13 及更低版本上将 CarPlay 添加到音频应用程序的唯一方法,但仍向后兼容 iOS 14(尽管 iOS 14 有一个新的 carplay 音频框架)。我所有的 CarPlay 逻辑都是在我的主 AppDelegate 的扩展中编写的(这可能有问题吗?)

在模拟器中,一切正常,音频在外部模拟汽车显示器中播放。但是我的团队在一辆真实的汽车上测试了这个应用程序,当从汽车显示屏上打开应用程序时,它立即崩溃了。

在 iOS 14.4 上的 iPhone 11 Pro 上测试时,我在这里有崩溃日志:

Exception Type:  EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000001, 0x00000001b88d13cc
Termination Signal: Trace/BPT trap: 5
Termination Reason: Namespace SIGNAL, Code 0x5
Terminating Process: exc handler [27455]
Triggered by Thread:  5

Thread 0 name:
Thread 0:
0   libsystem_kernel.dylib          0x00000001d6aa6f5c __ulock_wait + 8
1   libdispatch.dylib               0x00000001a8746794 _dlock_wait + 56 (lock.c:326)
2   libdispatch.dylib               0x00000001a87466c0 _dispatch_once_wait + 124 (lock.c:382)
3   UIKitCore                       0x00000001ab1080f8 -[_UIApplicationConfigurationLoader _loadInitializationContext] + 152 (once.h:84)
4   UIKitCore                       0x00000001ab108444 -[_UIApplicationConfigurationLoader applicationInitializationContext] + 32 (_UIApplicationConfigurationLoader.m:161)
5   UIKitCore                       0x00000001ab0ef05c -[_UIScreenInitialDisplayConfigurationLoader initialDisplayContext] + 180 (UIScreen.m:371)
6   UIKitCore                       0x00000001ab0ef348 +[UIScreen initialize] + 128 (UIScreen.m:626)
7   libobjc.A.dylib                 0x00000001bdb67c58 CALLING_SOME_+initialize_METHOD + 24 (objc-initialize.mm:384)
8   libobjc.A.dylib                 0x00000001bdb6e318 initializeNonMetaClass + 716 (objc-initialize.mm:554)
9   libobjc.A.dylib                 0x00000001bdb6f910 initializeAndMaybeRelock(objc_class*, objc_object*, mutex_tt<false>&, bool) + 280 (objc-runtime-new.mm:2221)
10  libobjc.A.dylib                 0x00000001bdb7e498 lookUpImpOrForward + 956 (objc-runtime-new.mm:2237)
11  libobjc.A.dylib                 0x00000001bdb68524 _objc_msgSend_uncached + 68
12  UIKitCore                       0x00000001ab33ef48 -[_UIRemoteKeyboards keyboardWindow] + 52 (_UIRemoteKeyboards.m:2036)
13  UIKitCore                       0x00000001ab33cf6c -[_UIRemoteKeyboards allowedToShowKeyboard] + 96 (_UIRemoteKeyboards.m:1588)
14  UIKitCore                       0x00000001ab33bda8 -[_UIRemoteKeyboards checkConnection] + 64 (_UIRemoteKeyboards.m:1315)
15  UIKitCore                       0x00000001ab338b60 -[_UIRemoteKeyboards init] + 156 (_UIRemoteKeyboards.m:797)
16  UIKitCore                       0x00000001ab338ab4 __43+[_UIRemoteKeyboards sharedRemoteKeyboards]_block_invoke + 20 (_UIRemoteKeyboards.m:785)
17  libdispatch.dylib               0x00000001a8745db0 _dispatch_client_callout + 20 (object.m:559)
18  libdispatch.dylib               0x00000001a87475c8 _dispatch_once_callout + 32 (once.c:52)
19  UIKitCore                       0x00000001ab338a9c +[_UIRemoteKeyboards sharedRemoteKeyboards] + 176 (once.h:84)
20  UIKitCore                       0x00000001ab50ccac _UIApplicationMainPreparations + 1348 (UIApplication.m:4644)
21  UIKitCore                       0x00000001ab50c740 UIApplicationMain + 140 (UIApplication.m:4704)
22  MyAppName                       0x000000010458fb04 main + 68 (UITextField+Extension.swift:22)
23  libdyld.dylib                   0x00000001a87866b0 start + 4

Thread 1:
0   libsystem_pthread.dylib         0x00000001f4608764 start_wqthread + 0

Thread 2:
0   libsystem_pthread.dylib         0x00000001f4608764 start_wqthread + 0

Thread 3 name:
Thread 3:
0   libsystem_kernel.dylib          0x00000001d6a822d0 mach_msg_trap + 8
1   libsystem_kernel.dylib          0x00000001d6a81660 mach_msg + 76 (mach_msg.c:103)
2   libdispatch.dylib               0x00000001a875e888 _dispatch_mach_send_and_wait_for_reply + 528 (mach.c:812)
3   libdispatch.dylib               0x00000001a875ec24 dispatch_mach_send_with_result_and_wait_for_reply + 56 (mach.c:1998)
4   libxpc.dylib                    0x00000001f4626e68 xpc_connection_send_message_with_reply_sync + 240 (connection.c:848)
5   BoardServices                   0x00000001c2599958 -[BSXPCServiceConnectionMessage _sendSynchronously:] + 332 (BSXPCServiceConnectionMessage.m:129)
6   BoardServices                   0x00000001c259a2cc -[BSXPCServiceConnectionMessage sendSynchronouslyWithError:] + 256 (BSXPCServiceConnectionMessage.m:182)
7   BoardServices                   0x00000001c2584afc __71+[BSXPCServiceConnectionProxy createImplementationOfProtocol:forClass:]_block_invoke + 824 (BSXPCServiceConnectionProxy.m:274)
8   UIKitServices                   0x00000001acb7fc6c -[UISApplicationSupportClient applicationInitializationContextWithParameters:] + 272 (UISApplicationSupportClient.m:77)
9   UIKitCore                       0x00000001ab108278 __63-[_UIApplicationConfigurationLoader _loadInitializationContext]_block_invoke_2 + 228 (_UIApplicationConfigurationLoader.m:135)
10  UIKitCore                       0x00000001ab108188 __UIAPPLICATION_IS_LOADING_INITIALIZATION_INFO_FROM_THE_SYSTEM__ + 28 (_UIApplicationConfigurationLoader.m:30)
11  UIKitCore                       0x00000001ab108160 __63-[_UIApplicationConfigurationLoader _loadInitializationContext]_block_invoke + 100 (_UIApplicationConfigurationLoader.m:106)
12  libdispatch.dylib               0x00000001a8745db0 _dispatch_client_callout + 20 (object.m:559)
13  libdispatch.dylib               0x00000001a87475c8 _dispatch_once_callout + 32 (once.c:52)
14  UIKitCore                       0x00000001ab1080f8 -[_UIApplicationConfigurationLoader _loadInitializationContext] + 152 (once.h:84)
15  UIKitCore                       0x00000001ab108408 __70-[_UIApplicationConfigurationLoader startPreloadInitializationContext]_block_invoke + 28 (_UIApplicationConfigurationLoader.m:154)
16  libdispatch.dylib               0x00000001a874424c _dispatch_call_block_and_release + 32 (init.c:1454)
17  libdispatch.dylib               0x00000001a8745db0 _dispatch_client_callout + 20 (object.m:559)
18  libdispatch.dylib               0x00000001a8756a68 _dispatch_root_queue_drain + 656 (inline_internal.h:2548)
19  libdispatch.dylib               0x00000001a8757120 _dispatch_worker_thread2 + 116 (queue.c:6777)
20  libsystem_pthread.dylib         0x00000001f46017d8 _pthread_wqthread + 216 (pthread.c:2223)
21  libsystem_pthread.dylib         0x00000001f460876c start_wqthread + 8

Thread 4:
0   libsystem_pthread.dylib         0x00000001f4608764 start_wqthread + 0

Thread 5 name:
Thread 5 Crashed:
0   FrontBoardServices              0x00000001b88d13cc -[FBSSceneParameters initWithSpecification:] + 228 (FBSSceneParameters.m:34)
1   FrontBoardServices              0x00000001b88d1320 -[FBSSceneParameters initWithSpecification:] + 56 (FBSSceneParameters.m:34)
2   FrontBoardServices              0x00000001b88d1dd8 -[FBSSceneParameters initWithXPCDictionary:] + 128 (FBSSceneParameters.m:150)
3   BaseBoard                       0x00000001ad165af4 _BSXPCDecodeObject + 1892 (BSXPCCoder.m:583)
4   BaseBoard                       0x00000001ad1639c0 _BSXPCDecodeObjectForKey + 268 (BSXPCCoder.m:459)
5   BoardServices                   0x00000001c2585f30 +[BSXPCServiceConnectionProxy decodeArguments:outArgs:fromMessage:forConnection:] + 1608 (BSXPCServiceConnectionProxy.m:592)
6   BoardServices                   0x00000001c2583ab0 -[BSXPCServiceConnectionProxy invokeMessage:onTarget:] + 276 (BSXPCServiceConnectionProxy.m:342)
7   BoardServices                   0x00000001c258a994 __63-[BSXPCServiceConnectionEventHandler connection:handleMessage:]_block_invoke + 536 (BSXPCServiceConnectionEventHandler.m:261)
8   BoardServices                   0x00000001c25a0284 BSXPCServiceConnectionExecuteCallOut + 316 (BSXPCServiceConnection.m:1049)
9   BoardServices                   0x00000001c258a708 -[BSXPCServiceConnectionEventHandler connection:handleMessage:] + 172 (BSXPCServiceConnectionEventHandler.m:250)
10  BoardServices                   0x00000001c259f668 -[BSXPCServiceConnection _connection_handleMessage:fromPeer:withHandoff:] + 572 (BSXPCServiceConnection.m:834)
11  libdispatch.dylib               0x00000001a874424c _dispatch_call_block_and_release + 32 (init.c:1454)
12  libdispatch.dylib               0x00000001a8745db0 _dispatch_client_callout + 20 (object.m:559)
13  libdispatch.dylib               0x00000001a874d10c _dispatch_lane_serial_drain + 580 (inline_internal.h:2548)
14  libdispatch.dylib               0x00000001a874dc90 _dispatch_lane_invoke + 460 (queue.c:3862)
15  libdispatch.dylib               0x00000001a874cfd8 _dispatch_lane_serial_drain + 272 (inline_internal.h:2589)
16  libdispatch.dylib               0x00000001a874dc90 _dispatch_lane_invoke + 460 (queue.c:3862)
17  libdispatch.dylib               0x00000001a8757d78 _dispatch_workloop_worker_thread + 708 (queue.c:6601)
18  libsystem_pthread.dylib         0x00000001f4601814 _pthread_wqthread + 276 (pthread.c:2210)
19  libsystem_pthread.dylib         0x00000001f460876c start_wqthread + 8

Thread 6 name:
Thread 6:
0   libsystem_kernel.dylib          0x00000001d6a822d0 mach_msg_trap + 8
1   libsystem_kernel.dylib          0x00000001d6a81660 mach_msg + 76 (mach_msg.c:103)
2   IOKit                           0x00000001b3b68340 io_hideventsystem_copy_property + 172 (IOHIDEventSystemMIGUser.c:3056)
3   IOKit                           0x00000001b3b22c60 IOHIDEventSystemClientCopyProperty + 128 (IOHIDEventSystemClient.c:1097)
4   IOKit                           0x00000001b3b22354 __IOHIDEventSystemClientRefresh + 1148 (IOHIDEventSystemClient.c:539)
5   IOKit                           0x00000001b3b230cc IOHIDEventSystemClientCreateWithType + 856 (IOHIDEventSystemClient.c:749)
6   BackBoardServices               0x00000001ac0dda88 ___getHIDEventSystemClient_block_invoke + 288 (BKSHIDEvent.m:93)
7   libdispatch.dylib               0x00000001a8745db0 _dispatch_client_callout + 20 (object.m:559)
8   libdispatch.dylib               0x00000001a87475c8 _dispatch_once_callout + 32 (once.c:52)
9   BackBoardServices               0x00000001ac0dd964 BKSHIDEventRegisterEventCallbackOnRunLoop + 152 (once.h:84)
10  UIKitCore                       0x00000001ab5babe4 -[UIEventFetcher threadMain] + 416 (UIEventFetcher.m:720)
11  Foundation                      0x00000001a9ee7a34 __NSThread__start__ + 864 (NSThread.m:724)
12  libsystem_pthread.dylib         0x00000001f45ffcb0 _pthread_start + 320 (pthread.c:881)
13  libsystem_pthread.dylib         0x00000001f4608778 thread_start + 8

Thread 7:
0   libsystem_pthread.dylib         0x00000001f4608764 start_wqthread + 0

Thread 5 crashed with ARM Thread State (64-bit):
    x0: 0x000000020ba16880   x1: 0x000000020ba16880   x2: 0x0000000000000000   x3: 0x00000000000008fd
    x4: 0x0000000000000000   x5: 0x00000001bdb9873e   x6: 0x000000000000006e   x7: 0x0000000000000fb0
    x8: 0x85f836c8121c001f   x9: 0x85f836c8121c001f  x10: 0x0000000000005403  x11: 0x0000000281a71540
   x12: 0x00000000000000aa  x13: 0x0000000000000001  x14: 0x00000000000000ac  x15: 0x0000000000000182
   x16: 0x00000002c6d90f88  x17: 0x0000000208ac3dc8  x18: 0x0000000000000000  x19: 0x0000000000000000
   x20: 0x0000000281472eb0  x21: 0x0000000000000000  x22: 0x0000000000000000  x23: 0x00000001f75f31f5
   x24: 0x000000020ba160d8  x25: 0x0000000000000000  x26: 0x00000001f7ff3288  x27: 0x000000020ba160b0
   x28: 0x0000000000000000   fp: 0x000000016bb2e130   lr: 0x86106081b88d1320
    sp: 0x000000016bb2e100   pc: 0x00000001b88d13cc cpsr: 0x60000000
   esr: 0xf2000000  Address size fault

什么可能导致应用程序在真车中崩溃但在模拟器中运行良好?这是我的 AppDelegate 的一部分,我在其中调用一个函数来设置 carplay:

import UIKit
import AVFoundation
import AVKit
import GoogleInteractiveMediaAds
import MediaPlayer
import GoogleMobileAds
import UserNotifications
import WebKit
import SafariServices
import Hero
import Firebase

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    static let reachable = "Reachable"
    static let unReachable = "UnReachable"
    let reachability = try! Reachability()
    var iOSStream: String?
    var preRolladUrl: String?
    var window: UIWindow?
    var adType: String?
    var adServer: String?
    var adFeed: String?
    var miniPlayer: PlayerPopupControlViewController?
    var selectedStation: Players!
    
    // CarPlay
    var playableContentManager: MPPlayableContentManager?
    let carplayPlaylist = CarPlayPlaylist()
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        
        UINavigationBar.appearance().barTintColor = UIColor.black
        UINavigationBar.appearance().tintColor = UIColor.black
        UINavigationBar.appearance().titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white]
        UINavigationBar.appearance().isTranslucent = false
        
        if UserDefaults.standard.object(forKey: UserDefaultsConstants.resumeRadioInBackground) == nil {
            UserDefaults.standard.set(true, forKey: UserDefaultsConstants.resumeRadioInBackground)
            UserDefaults.standard.synchronize()
        }
        self.setupBaseURL()
        // Override point for customization after application launch.
        self.startObservingReachability()
        
        UIApplication.shared.beginReceivingRemoteControlEvents()
        do {
            try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playback)
            try AVAudioSession.sharedInstance().setActive(true)
            
        } catch  {
            AppLogger.error(error)
        }
        UNUserNotificationCenter.current().delegate = self
        UserDefaults.standard.set(false, forKey: UserDefaultsConstants.isMiniPlayerDisplayed)
        UserDefaults.standard.synchronize()
        SettingsDataManager.sharedInstance.selectedStation = SettingsDataManager.sharedInstance.getSelectedStationFromUserDefaults()
        registerForPushNotifications()
        
        setupCarPlay()
        
        FirebaseApp.configure()
        
        return true
    }
    

AppDelegate+CarPlay.swift

import Foundation
import MediaPlayer

extension AppDelegate{
    func setupCarPlay() {
        playableContentManager = MPPlayableContentManager.shared()
        
        playableContentManager?.delegate = self
        playableContentManager?.dataSource = self
        
        self.carplayPlaylist.setupCommandCenter()
    }
}

extension AppDelegate: MPPlayableContentDelegate {
    
    // This is called when user selects a 'playable' item (MPContentItem)
    func playableContentManager(_ contentManager: MPPlayableContentManager, initiatePlaybackOfContentItemAt indexPath: IndexPath, completionHandler: @escaping (Error?) -> Void) {
        
        self.carplayPlaylist.playerData = SettingsDataManager.sharedInstance.playerData ?? []
//        guard let miniPlayer = self.miniPlayer else {return}
        
        DispatchQueue.main.async {
            // App should play music either from the radio stream or podcasts
            if indexPath.count == 2 {
                
                if(indexPath[0] == 0) {
                    // When user selects playable item within Radio tab
                    if (self.carplayPlaylist.playerData.count > 0) {
                        if let stationURL = URL(string: self.carplayPlaylist.playerData[indexPath[1]].streams?.iOS ?? "") {
                            self.carplayPlaylist.play(playURL: stationURL)
                            SettingsDataManager.sharedInstance.selectedStation = self.carplayPlaylist.playerData[indexPath[1]]
                        }
                    }
                }
                
            }
            
            completionHandler(nil)
            
            // Workaround to make the Now Playing working on the simulator:
            #if targetEnvironment(simulator)
                UIApplication.shared.endReceivingRemoteControlEvents()
                UIApplication.shared.beginReceivingRemoteControlEvents()
            #endif
        }
    }
    
    func beginLoadingChildItems(at indexPath: IndexPath, completionHandler: @escaping (Error?) -> Void) {
        carplayPlaylist.load { error in
            completionHandler(error)
        }
    }
}

extension AppDelegate: MPPlayableContentDataSource {
    
    func numberOfChildItems(at indexPath: IndexPath) -> Int {
        if indexPath.indices.count == 0 {
            // This returns the number of tabs at the top of the CarPlay display
            return 1 // changed to 1 to allow only radio streams
            
        } else if indexPath.indices.count == 1 {
            // This returns the number of rows within each tab
            if indexPath[0] == 0 {
                // Radio Stations rows
                return carplayPlaylist.playerData.count
            } else {
                // Podcasts feed rows
         
                return 0 // Return 0 while podcasts are disabled
            }
            

        } else {
            return 0
        }
        
    }
    
    func contentItem(at indexPath: IndexPath) -> MPContentItem? {
        let playerData = carplayPlaylist.playerData
//        let podCastsFeeds = carplayPlaylist.podCastSettings?.podcasts_feeds

        if indexPath.count == 1 {
            // Tab section
            let item: MPContentItem
            if (indexPath[0] == 0) {
                // Radio Stations Tab Section
                
                item = MPContentItem(identifier: "Radio")
                item.title = "Radio"
                item.artwork = MPMediaItemArtwork(boundsSize: #imageLiteral(resourceName: "NavIcon-Broadcast").size, requestHandler: { _ -> UIImage in
                    return #imageLiteral(resourceName: "NavIcon-Broadcast")
                })
            } else {
                // Podcast Tab Section
                
                item = MPContentItem(identifier: "Podcasts")
                item.title = "Podcasts"
                item.artwork = MPMediaItemArtwork(boundsSize: #imageLiteral(resourceName: "NavIcon-Podcasts").size, requestHandler: { _ -> UIImage in
                    return #imageLiteral(resourceName: "NavIcon-Podcasts")
                })
            }
            item.isContainer = true
            item.isPlayable = false
            
            return item
            
        } else if indexPath.count == 2, indexPath.item < playerData.count, indexPath[0] == 0 {
            // Radio station items section
            
            let station = playerData[indexPath.item]
            let item = MPContentItem(identifier: "\(station.name)")
            item.title = station.name
            item.subtitle = station.call_letters
            item.isPlayable = true
            item.isStreamingContent = true
            item.downloadImageAndSetArtwork(from: station.logo ?? "", completion: {})
            
            return item
            
        } else {
            return nil
        }
    }
    
}

///extension to downlaod the image from the api
extension MPContentItem {
    func getData(from url: URL, completion: @escaping (Data?, URLResponse?, Error?) -> ()) {
        URLSession.shared.dataTask(with: url, completionHandler: completion).resume()
    }
    
    func downloadImageAndSetArtwork(from address: String, completion: @escaping () -> Void) {
        let defaultImage = #imageLiteral(resourceName: "NavIcon-Music")
        let defaultArtwork = MPMediaItemArtwork(boundsSize: defaultImage.size, requestHandler: { _ -> UIImage in
            return defaultImage
        })
        
        guard let url = URL(string: address) else {
            self.artwork = defaultArtwork
            return
        }
        getData(from: url) {
            data, response, error in
            guard let data = data, error == nil else {
                AppLogger.error("Image Error")
                self.artwork = defaultArtwork
                return
            }
            DispatchQueue.main.async() {
                guard let image = UIImage(data: data) else {
                    self.artwork = defaultArtwork
                    return
                }
                
                self.artwork = MPMediaItemArtwork(boundsSize: image.size, requestHandler: { _ -> UIImage in
                    return image
                })

                completion()
            }
        }
        
    }
    
}

CarPlayPlaylist.swift

import Foundation
//import UIKit
import AVKit
import MediaPlayer


class CarPlayPlaylist {

    let radioPlayer = FRadioPlayer.shared
    var playerData: [Players] = []
    var podCastItemsArray: [[Item]] = []
    var podCastSettings: Podcast_settings?
    var podCastFeedNameArray:[String] = []
    var isFromCarPlay: Bool = false
    var playButtonStatus: Bool = false
    var currentPodcastItem: Item?
    
    func load(_ completion: @escaping (Error?) -> Void) {

//        if (self.podCastFeedNameArray.count == 0 && self.podCastItemsArray.count == 0) {
//            getPodcastDataFromSettingsDataManager()
//
//            let podcastFeedsCount = self.podCastSettings?.podcasts_feeds?.count ?? 0
//            podCastItemsArray = [[Item]](repeating: [], count: podcastFeedsCount)
//        }
        
        self.playerData = SettingsDataManager.sharedInstance.playerData ?? []
        completion(nil)
    }
    
    
    func play (playURL: URL) {
            isFromCarPlay = true
            self.radioPlayer.radioURL = playURL
            self.radioPlayer.play()
    }
    
    func setupCommandCenter () {

        MPNowPlayingInfoCenter.default().nowPlayingInfo = [MPMediaItemPropertyTitle: "Current Playing song"]
        MPNowPlayingInfoCenter.default().nowPlayingInfo![MPNowPlayingInfoPropertyPlaybackRate] = 0.0

        let commandCenter = MPRemoteCommandCenter.shared()
        commandCenter.playCommand.isEnabled = true
        commandCenter.pauseCommand.isEnabled = true
        commandCenter.playCommand.addTarget { [weak self] (event) -> MPRemoteCommandHandlerStatus in
            self?.radioPlayer.play()
//            NotificationCenter.default.post(name: NSNotification.Name(rawValue: NotificationCenterConstants.carPlayDidPlay), object: nil, userInfo: nil)
            
            return .success
        }
        commandCenter.pauseCommand.addTarget { [weak self] (event) -> MPRemoteCommandHandlerStatus in
            self?.radioPlayer.pause()
//            NotificationCenter.default.post(name: NSNotification.Name(rawValue: NotificationCenterConstants.carPlayDidPause), object: nil, userInfo: nil)

            return .success
        }
    }
    
}

extension CarPlayPlaylist {
    func addCommandCenterNotificationObservers() {
        NotificationCenter.default.addObserver(self, selector: #selector(commandCenterDidPlay), name: NSNotification.Name(rawValue: NotificationCenterConstants.commandCenterDidPlay), object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(commandCenterDidPause), name: NSNotification.Name(rawValue: NotificationCenterConstants.commandCenterDidPause), object: nil)
    }
    
    func removeCommandCenterObservers() {
        NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NotificationCenterConstants.commandCenterDidPlay), object: nil)
        NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NotificationCenterConstants.commandCenterDidPause), object: nil)
    }
    
    @objc func commandCenterDidPlay() {
        // Playback rate should change the playback status
        MPNowPlayingInfoCenter.default().nowPlayingInfo?[MPNowPlayingInfoPropertyPlaybackRate] = 0.0

    }
    
    @objc func commandCenterDidPause() {
        // Playback rate should change the playback status
        MPNowPlayingInfoCenter.default().nowPlayingInfo?[MPNowPlayingInfoPropertyPlaybackRate] = 1.0

    }
}
4

0 回答 0