Created
September 14, 2012 21:47
-
-
Save spoletto/3725118 to your computer and use it in GitHub Desktop.
iOS 6 Autorotation Swizzling
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@implementation AppDelegate | |
void SwapMethodImplementations(Class cls, SEL left_sel, SEL right_sel) { | |
Method leftMethod = class_getInstanceMethod(cls, left_sel); | |
Method rightMethod = class_getInstanceMethod(cls, right_sel); | |
method_exchangeImplementations(leftMethod, rightMethod); | |
} | |
+ (void)initialize { | |
if (self == [AppDelegate class]) { | |
#ifdef __IPHONE_6_0 | |
SwapMethodImplementations([UIViewController class], @selector(supportedInterfaceOrientations), @selector(sp_supportedInterfaceOrientations)); | |
SwapMethodImplementations([UIViewController class], @selector(shouldAutorotate), @selector(sp_shouldAutorotate)); | |
#endif | |
} | |
} | |
@end | |
@implementation UIViewController (iOS6Autorotation) | |
#ifdef __IPHONE_6_0 | |
/* | |
* We've swizzled the new iOS 6 autorotation callbacks onto their iOS 5 and iOS 4 equivalents | |
* to preserve existing functionality. | |
* | |
*/ | |
- (BOOL)sp_shouldAutorotate { | |
BOOL shouldAutorotate = YES; | |
if ([self respondsToSelector:@selector(shouldAutorotateToInterfaceOrientation:)]) { | |
NSUInteger mask = 0; | |
if ([self shouldAutorotateToInterfaceOrientation:UIInterfaceOrientationPortrait]) { | |
mask |= UIInterfaceOrientationMaskPortrait; | |
} | |
if ([self shouldAutorotateToInterfaceOrientation:UIInterfaceOrientationLandscapeLeft]) { | |
mask |= UIInterfaceOrientationMaskLandscapeLeft; | |
} | |
if ([self shouldAutorotateToInterfaceOrientation:UIInterfaceOrientationLandscapeRight]) { | |
mask |= UIInterfaceOrientationMaskLandscapeRight; | |
} | |
if ([self shouldAutorotateToInterfaceOrientation:UIInterfaceOrientationPortraitUpsideDown]) { | |
mask |= UIInterfaceOrientationMaskPortraitUpsideDown; | |
} | |
if (mask == 0) { | |
// Shouldn't autorotate to *any* orientation. | |
shouldAutorotate = NO; | |
} | |
} else { | |
// This actually calls the original method implementation | |
// instead of recursively calling into this method implementation. | |
shouldAutorotate = [self sp_shouldAutorotate]; | |
} | |
return shouldAutorotate; | |
} | |
- (NSUInteger)sp_supportedInterfaceOrientations { | |
NSUInteger mask = 0; | |
/* | |
* In iOS 6, Apple dramatically changed the way autorotation works. | |
* Rather than having each view controller respond to shouldAutorotateToInterfaceOrientation: | |
* to specify whether or not it could support a particular orientation, the responsibility was | |
* shifted to top-level container view controllers. That means UINavigationController becomes | |
* responsible for declaring whether or not an orientation is supported. Since our app | |
* has logic for how to autorotate on a per view controller basis, we call through to the | |
* swizzled version of supportedInterfaceOrientations for the topViewController. | |
* | |
*/ | |
if ([self isKindOfClass:[UINavigationController class]]) { | |
return [[(UINavigationController *)self topViewController] supportedInterfaceOrientations]; | |
} | |
if ([self respondsToSelector:@selector(shouldAutorotateToInterfaceOrientation:)]) { | |
if ([self shouldAutorotateToInterfaceOrientation:UIInterfaceOrientationPortrait]) { | |
mask |= UIInterfaceOrientationMaskPortrait; | |
} | |
if ([self shouldAutorotateToInterfaceOrientation:UIInterfaceOrientationLandscapeLeft]) { | |
mask |= UIInterfaceOrientationMaskLandscapeLeft; | |
} | |
if ([self shouldAutorotateToInterfaceOrientation:UIInterfaceOrientationLandscapeRight]) { | |
mask |= UIInterfaceOrientationMaskLandscapeRight; | |
} | |
if ([self shouldAutorotateToInterfaceOrientation:UIInterfaceOrientationPortraitUpsideDown]) { | |
mask |= UIInterfaceOrientationMaskPortraitUpsideDown; | |
} | |
} else { | |
// This actually calls the original method implementation | |
// instead of recursively calling into this method implementation. | |
mask = [self sp_supportedInterfaceOrientations]; | |
} | |
return mask; | |
} | |
#endif | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
as @davedelong said on twitter: "I love the runtime as much (or more) than the next guy, but you should absolutely not use [this] code."