How can I make the Control Center slider editable?

There is the changePlaybackPositionCommand API with the associated Event MPChangePlaybackPositionCommandEvent.positionTime (see https://developer.apple.com/library/ios/releasenotes/General/iOS91APIDiffs/Objective-C/MediaPlayer.html)

I tried

[commandCenter.changePlaybackPositionCommand
                     addTarget: self
                        action: @selector( onChangePlaybackPositionCommand: )]

with the associated method

- (MPRemoteCommandHandlerStatus) onChangePlaybackPositionCommand:
                                     (MPChangePlaybackPositionCommandEvent *) event
{
    NSLog(@"changePlaybackPosition to %f", event.positionTime);
    return MPRemoteCommandHandlerStatusSuccess;
}

but the cursor is still not movable and the method is not called. I guess I still miss something


The New Way for iOS 12+ and Swift 4+

Following is an improved way of handling scrubbing in Remote Play Center:

// Handle remote events
func setupRemoteTransportControls() {
    let commandCenter = MPRemoteCommandCenter.shared()
        
    // Scrubber
    commandCenter.changePlaybackPositionCommand.addTarget { [weak self](remoteEvent) -> MPRemoteCommandHandlerStatus in
        guard let self = self else {return .commandFailed}
        if let player = self.player {
           let playerRate = player.rate
           if let event = remoteEvent as? MPChangePlaybackPositionCommandEvent {
               player.seek(to: CMTime(seconds: event.positionTime, preferredTimescale: CMTimeScale(1000)), completionHandler: { [weak self](success) in
                   guard let self = self else {return}
                   if success {
                       self.player?.rate = playerRate
                   }
               })
               return .success
            }
        }
        return .commandFailed
    }

    // Register to receive events
    UIApplication.shared.beginReceivingRemoteControlEvents()
}

In addition to implementing the callback, it seems that you would have to set the canBeControlledByScrubbing property to true. Unfortunately, there is no public accessor to set it, so you would have to do it as follows (and won't be able to submit your app to the AppStore):

NSNumber *shouldScrub = [NSNumber numberWithBool:YES];
[[[MPRemoteCommandCenter sharedCommandCenter] changePlaybackPositionCommand]
     performSelector:@selector(setCanBeControlledByScrubbing:) withObject:shouldScrub];
[[[MPRemoteCommandCenter sharedCommandCenter] changePlaybackPositionCommand]
            addTarget:self
               action:@selector(handleChangePlaybackPositionCommand:)];

If you do it like this, you will get the callback on your handleChangePlaybackPositionCommand: method, taking an MPChangePlaybackPositionCommandEvent as its only parameter.

If you do want to support older versions of iOS than 9.1, I'd suggest to check for the iOS version before executing the above code to prevent crashes (You can either do it using the new API introduced with iOS 8, or if you want to support iOS 7 and earlier as well, using something like

[[[UIDevice currentDevice] systemVersion] compare:@"9.1" options:NSNumericSearch] != NSOrderedAscending

I hope this helps :-)


As of 2020 with Swift 5, if we only use commandCenter.changePlaybackPositionCommand it won't work, we also need to set metadata with MPMediaItemPropertyPlaybackDuration for the player then we can use the slider.

Check this article from Apple: https://developer.apple.com/documentation/avfoundation/media_assets_playback_and_editing/creating_a_basic_video_player_ios_and_tvos/controlling_background_audio

Look at the section: Provide Display Metadata