iosorientationscreen-rotationmpvolumeview

MPVolumeView route list is supporting all orientations and ignoring underlying view controller


This appears to be an OS bug, but a workaround is still needed.

Targeting iOS 8 or 9, using view controller based orientation, MPVolumeView's route list will always rotate, even if its parent view controller only supports a single orientation.

This can cause the system to get into an incorrect orientation state where the view controller is shown in portrait, but the status bar (and control center) are landscape.

Have created a test project that demonstrates the bug: https://github.com/NextFaze/MPVolumeViewTest


Solution

  • hacky solution using swizzling:

    #import "UIViewController+RoutingSheet.h"
    #import <objc/runtime.h>
    
    @implementation UIViewController (RoutingSheet)
    
    + (void)load {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            SEL originalSelector = @selector(shouldAutorotate);
            SEL swizzledSelector = @selector(shouldAutoRotateOverrideRoutingSheet);
            Method originalMethod = class_getInstanceMethod(self, originalSelector);
            Method extendedMethod = class_getInstanceMethod(self, swizzledSelector);
            method_exchangeImplementations(originalMethod, extendedMethod);
        });
    }
    
    - (UIWindow *)currentWindow {
        for (UIWindow *window in [[UIApplication sharedApplication] windows]) {
            if (window.rootViewController == self)
                return window;
        }
        return nil;
    }
    
    - (BOOL)shouldAutoRotateOverrideRoutingSheet {
        UIWindow *window = [self currentWindow];
        if (window != nil) {
            NSString *className = NSStringFromClass(window.class);
            if ([className containsString:@"MPAVRoutingSheetSecureWindow"]) {
                return NO;
            }
        }
        return [self shouldAutoRotateOverrideRoutingSheet];
    }
    
    @end