Skip to content

Instantly share code, notes, and snippets.

@0xced
Created December 11, 2014 13:25
Show Gist options
  • Select an option

  • Save 0xced/fc0dbc952989fe989c54 to your computer and use it in GitHub Desktop.

Select an option

Save 0xced/fc0dbc952989fe989c54 to your computer and use it in GitHub Desktop.
Restore MPMoviePlayerController controls autohide behavior after unlocking a device
/**
* Locking then unlocking a device while a movie is playing disables controls autohiding.
* `MPInlineVideoController` registers for the (private) UIApplicationResumedEventsOnlyNotification
* (which is sent between UIApplicationWillEnterForegroundNotification and UIApplicationDidBecomeActiveNotification).
* In its callback (-[MPInlineVideoController _applicationResumedEventsOnly:]) it calls `[self setDisableControlsAutohide:YES]`
* effectively disabling controls autohide. In order to restore the automatic hiding of controls, we call
* setDisableControlsAutohide:NO when UIApplicationDidBecomeActiveNotification is posted.
*/
#import <MediaPlayer/MediaPlayer.h>
static void EnableControlsAutohide(MPMoviePlayerController *moviePlayerController)
{
NSString *videoViewController = [@[ @"video", @"View", @"Controller" ] componentsJoinedByString:@""];
NSString *inlineVideoControllerKeyPath = [@[ @"implementation", videoViewController ] componentsJoinedByString:@"."];
@try
{
id inlineVideoController = [moviePlayerController valueForKeyPath:inlineVideoControllerKeyPath];
SEL selector = NSSelectorFromString([@[ @"set", @"Disable", @"Controls", @"Autohide", @":" ] componentsJoinedByString:@""]);
NSMethodSignature *methodSignature = [inlineVideoController methodSignatureForSelector:selector];
if (methodSignature.numberOfArguments != 3)
return;
const char *returnType = methodSignature.methodReturnType;
const char *firstArgType = [methodSignature getArgumentTypeAtIndex:2];
if (strcmp(returnType, @encode(void)) == 0 && strcmp(firstArgType, @encode(BOOL)) == 0)
{
// Equivalent to [inlineVideoController setDisableControlsAutohide:NO], i.e. enable controls autohide which is the default behavior
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];
[invocation setTarget:inlineVideoController];
[invocation setSelector:selector];
BOOL disableControlsAutohide = NO;
[invocation setArgument:&disableControlsAutohide atIndex:2];
[invocation invoke];
}
}
@catch (NSException *exception)
{
NSLog(@"%@", exception);
}
}
@implementation NSObject (FixMPMoviePlayerControllerControlsAutohide)
+ (void) load
{
static __weak MPMoviePlayerController *currentMoviePlayerController;
dispatch_async(dispatch_get_main_queue(), ^{
NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
[defaultCenter addObserverForName:MPMoviePlayerNowPlayingMovieDidChangeNotification object:nil queue:mainQueue usingBlock:^(NSNotification *notification) {
currentMoviePlayerController = notification.object;
}];
[defaultCenter addObserverForName:MPMoviePlayerPlaybackDidFinishNotification object:nil queue:mainQueue usingBlock:^(NSNotification *notification) {
currentMoviePlayerController = nil;
}];
[defaultCenter addObserverForName:UIApplicationDidBecomeActiveNotification object:nil queue:mainQueue usingBlock:^(NSNotification *notification) {
MPMoviePlayerController *moviePlayerController = currentMoviePlayerController;
if (moviePlayerController)
EnableControlsAutohide(moviePlayerController);
}];
});
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment