Unpredictable NowPlayable Behavior SwiftUI

37 views Asked by At

I have an app which features a tiktok-like vertical scroll of videos and horizontal carousel of different categories. I update the lock screen info each time the video changes like so:

    // Function to update static metadata
    func updateStaticInfo(for video: Video) {

        var metadata : [AVMutableMetadataItem] = VideoMetadata(title: video.title, 
                                                               authorName: video.author.name ?? "Vastly",
                                                               bio: video.bio,
                                                               publisher: "Vastly").externalMetadata()
        
        if let url = video.author.fileName {
            URLSession.shared.dataTask(with: url) { data, response, error in
                guard let data = data, error == nil else {
                    print("Error downloading image: \(error?.localizedDescription ?? "Unknown error")")
                    return
                }
                
                // Create the artwork metadata item
                let imageItem = AVMutableMetadataItem()
                imageItem.identifier = .commonIdentifierArtwork
                imageItem.value = data as NSData
                
                // Append to metadata array
                metadata.append(imageItem)
                
                self.getPlayer(for: video).items().last?.externalMetadata = metadata
                MPNowPlayingInfoCenter.default().nowPlayingInfo = self.getPlayer(for: video).items().last?.nowPlayingInfo
            }.resume()
        }
        self.getPlayer(for:  video).items().last?.externalMetadata = metadata
        MPNowPlayingInfoCenter.default().nowPlayingInfo = self.getPlayer(for: video).items().last?.nowPlayingInfo
    }

However, when the video changes from the lockscreen — despite this being properly called — the metadata doesn't update.

Similarly, I can't change the command center controls for some reason. Here is my code for it, however, the skip back/forward controls are still shown and the next/previous track are not.

    // this function initializes the physical command center controls.
    func setupCommandCenter() {
        print("**** Setup Command Center")
        
        let commandCenter = MPRemoteCommandCenter.shared()

        // Remove all targets to ensure a clean state
        commandCenter.changePlaybackPositionCommand.removeTarget(nil)
        commandCenter.skipForwardCommand.removeTarget(nil)
        commandCenter.skipBackwardCommand.removeTarget(nil)
        commandCenter.playCommand.removeTarget(nil)
        commandCenter.pauseCommand.removeTarget(nil)
        commandCenter.nextTrackCommand.removeTarget(nil)
        commandCenter.previousTrackCommand.removeTarget(nil)
        commandCenter.skipForwardCommand.removeTarget(nil)
        commandCenter.skipBackwardCommand.removeTarget(nil)

        // Set up command center targets
        commandCenter.playCommand.addTarget { [unowned self] _ in
            if let video = self.getCurrentVideo(), self.getPlayer(for: video).rate == 0 {
                self.playCurrentVideo()
                print("**** Successful Lockscreen action: Play")
                return .success
            }
            return .commandFailed
        }
        
        commandCenter.pauseCommand.addTarget { [unowned self] _ in
            if let video = self.getCurrentVideo(), self.getPlayer(for: video).rate > 0 {
                self.pauseCurrentVideo()
                print("**** Successful Lockscreen action: Pause")
                return .success
            }
            return .commandFailed
        }

        commandCenter.changePlaybackPositionCommand.addTarget { [unowned self] (event) -> MPRemoteCommandHandlerStatus in
            let player = self.getPlayer(for: self.getCurrentVideo() ?? EMPTY_VIDEO)
            if let event = event as? MPChangePlaybackPositionCommandEvent {
                player.seek(to: CMTime(seconds: event.positionTime, preferredTimescale: 1))
                print("**** Successful Lockscreen action: Scrub")
                return .success
            }
            print("**** Unsuccessful Lockscreen action: Scrub")
            return .commandFailed
        }
        
        commandCenter.nextTrackCommand.addTarget { [unowned self] _ in
            if let video = self.catalog.nextVideo() {
                print("**** Successful Lockscreen action: Next")
                return .success
            }
            return .commandFailed
        }
        
        commandCenter.previousTrackCommand.addTarget { [unowned self] _ in
            if let video = self.catalog.previousVideo() {
                print("**** Successful Lockscreen action: Previous")
                return .success
            }
            return .commandFailed
        }
        
        commandCenter.changePlaybackPositionCommand.isEnabled = true
        commandCenter.playCommand.isEnabled = true
        commandCenter.pauseCommand.isEnabled = true
        commandCenter.togglePlayPauseCommand.isEnabled = true
        commandCenter.skipForwardCommand.isEnabled = false
        commandCenter.skipBackwardCommand.isEnabled = false
        commandCenter.nextTrackCommand.isEnabled = true
        commandCenter.previousTrackCommand.isEnabled = true
        
        self.commandCenter = commandCenter
    }

Anyone able to help?

EDIT: I've tried using the nowPlayingInfo to update the lockscreen metadata, and it would flash off/on and disappear when interacted with. The external metadata seems to work better for now.

0

There are 0 answers