如何在iOS 6中以编程方式更改设备方向
在iOS 5中,我们可以像这样以编程方式更改设备方向:
[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight];
但在iOS 6中, setOrientation
已被弃用,我如何在iOS 6中以编程方式更改设备方向?
这是我的“五美分”,在iOS7上使用ARC进行testing
[[UIDevice currentDevice] setValue: [NSNumber numberWithInteger: UIInterfaceOrientationPortrait] forKey:@"orientation"];
这不会像performSelector一样产生“泄漏”警告。
UIAlertView – 有了这段代码,当你在视图中打开UIAlertView(will / Did)的时候,你会注意到除了这个视图外,其他所有视图都是纵向的(苹果,真的吗?)我不能强制视图redirect,但是发现如果你打开UIAlertView之前稍微延迟,然后查看有时间来改变方向。
请注意 ,我将于2014年9月12日发布我的应用程序周,如果通过或失败,我将更新post。
我发现强制设备改变方向的最简单的方法是提供一个新的视图控制器(使用presentViewController:animated:completion:
,其中新的视图控制器指定了一个特定的首选方向(通过实现方法-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
)。
如预期的那样,当呈现新的视图控制器时,方向将改变为新的视图控制器所优选的方向。 因此,最简单的实现(最佳实践)是将所需的所有function以特定方向embedded到单独的视图控制器中,并根据需要呈现。 系统将负责为您改变方向。
显然这可能不适合所有用例,但幸运的是,同样的技巧也适用于强制设备改变现有视图控制器的方向。
诀窍是提出一个新的视图控制器与您需要的特定首选方向,然后立即隐藏它。 这将导致方向在新的视图控制器出现时暂时改变。 最好的部分是,当新视图控制器被解散时,原始(呈现)视图控制器的preferredInterfaceOrientationForPresentation
被再次查询,您可以在这里指定你想要的最终方向。
在这里要注意的一件重要的事情是在原始视图控制器中临时禁用自动旋转(当从新呈现 – 然后被解除的视图控制器返回时),以便当用户将手机朝向新的方向旋转时,触发进一步自动旋转。
下面的代码应该说明我的观点,我的例子强制旋转到肖像,只要相应地改变,如果你想要其他的方向。
假设您有原始视图控制器名为Original
和名为ForcePortrait
临时视图控制器
@interface Original : UIViewController { BOOL orientationToPortrait; //should set to NO by default } @end @implementation Original - (UIInterfaceOrientation) preferredInterfaceOrientationForPresentation { if(orientationToPortrait) { //when we manually changed, show in Portrait return UIInterfaceOrientationPortrait; } else { //before manual orientation change, we allow any orientation return self.interfaceOrientation; } } -(BOOL) shouldAutorotate { //we should 'lock' the rotation once we manually change it return !orientationToPortrait; } -(void) changeOrientationToPortrait { //Sample method to change the orientation //when called, will show (and hide) the temporary view //Original.preferredInterfaceOrientationForPresentation will be called again after this method //flag this to ensure that we tell system we prefer Portrait, whenever it asked again orientationToPortrait = YES; //presenting the following VC will cause the orientation to temporary change //when the new VC is dismissed, system will ask what is our (Original) orientation preference again ForcePortrait* forcePortrait = [[ForcePortrait alloc] init]; [self presentViewController:forcePortrait animated:NO completion:^{ [forcePortrait dismissViewControllerAnimated:NO completion:nil]; }]; } @end @interface ForcePortrait : UIViewController @end @implementation ForcePortrait - (NSUInteger)supportedInterfaceOrientations { return UIInterfaceOrientationMaskPortrait; } - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation { return UIInterfaceOrientationPortrait; } @end
这不会回答如何更改设备方向,但可能会帮助您的其他信息。
iOS 6 UI界面方向 – shouldAutorotateToInterfaceOrientation :不工作
方法shouldAutorotateToInterfaceOrientation :不支持在iOS 6中。它的弃用。 以防万一,如果你是一个新手,谁只是盯着cocoa工作,并想知道为什么你的视图控制器在iOS 6中搞砸了,在iOS 5完美,只是知道shouldAutorotateToInterfaceOrientation :不再支持。 即使它可以适用于Xcode 4到4.3,但它不能在Xcode 4.5上工作。
苹果公司提供了一个新的方法来完成这个事情,在一个更清洁的方式。 您改为使用supportedInterfaceOrientations 。 它返回视图控制器支持的所有接口方向,接口方向值的掩码。
UIInterfaceOrientationMask枚举:
这些常量是屏蔽位,用于指定视图控制器支持的接口方向。
typedef enum { UIInterfaceOrientationMaskPortrait = (1 << UIInterfaceOrientationPortrait), UIInterfaceOrientationMaskLandscapeLeft = (1 << UIInterfaceOrientationLandscapeLeft), UIInterfaceOrientationMaskLandscapeRight = (1 << UIInterfaceOrientationLandscapeRight), UIInterfaceOrientationMaskPortraitUpsideDown = (1 << UIInterfaceOrientationPortraitUpsideDown), UIInterfaceOrientationMaskLandscape = (UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight), UIInterfaceOrientationMaskAll = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskPortraitUpsideDown), UIInterfaceOrientationMaskAllButUpsideDown = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight), } UIInterfaceOrientationMask;
使用shouldAutorotateToInterfaceOrientation:方法:
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation { return UIInterfaceOrientationIsLandscapeRight(toInterfaceOrientation); }
使用supportedInterfaceOrientations方法:
-(NSUInteger)supportedInterfaceOrientations{ return UIInterfaceOrientationMaskLandscapeRight; }
这些是UIViewController有关iOS6方向的附加方法
-
UIViewController preferredInterfaceOrientationForPresentation
-
UIViewController shouldAutorotate
-
UIViewController supportedInterfaceOrientations
在iOS6中添加了有关定位的UIApplication的方法
-
UIApplication supportedInterfaceOrientationsForWindow:
-
UIInterfaceOrientationMask
尝试这个:
#import <objc/message.h> if(UIDeviceOrientationIsLandscape(self.interfaceOrientation)){ if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) { objc_msgSend([UIDevice currentDevice], @selector(setOrientation:), UIInterfaceOrientationPortrait ); } }
你应该放置
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
在你的AppDelegate didFinishLaunchingWithOptions
方法中。
然后,在你的应用程序的任何地方,你可以得到当前的方向:
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
和testing方向:
UIInterfaceOrientationIsPortrait(orientation) UIInterfaceOrientationIsLandscape(orientation)
像,像
if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation)) { // code for landscape orientation // OR [[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight]; // OR [[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeLeft]; } else if (UIDeviceOrientationIsPortrait([UIDevice currentDevice].orientation)) { // code for Portrait orientation // OR [[UIDevice currentDevice] setOrientation:UIInterfaceOrientationPortraitUpsideDown]; // OR [[UIDevice currentDevice] setOrientation:UIInterfaceOrientationPortrait]; }
此代码适用于iOS 8或更高版本
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft]; [[UIDevice currentDevice] setValue:value forKey:@"orientation"];
试试这个…它为我解决了…
UIWindow *window = [[UIApplication sharedApplication] keyWindow]; UIView *view = [window.subviews objectAtIndex:0]; [view removeFromSuperview]; [window addSubview:view];
@implementation UINavigationController(自动旋转)
-(NSUInteger)supportedInterfaceOrientations { //make the check for iphone/ipad here if(IPHONE) { return UIInterfaceOrientationMaskPortrait; } else { return UIInterfaceOrientationMaskLandscape; } } - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation { return UIInterfaceOrientationPortrait; } - (BOOL)shouldAutorotate { return NO; }
如果您想避免使用运行时库,请对Bissy的答案稍作修改:
if (UIDeviceOrientationIsLandscape([[UIDevice currentDevice] orientation])) { if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) { int orientationPortrait = UIInterfaceOrientationPortrait; NSMethodSignature *sig = [[UIDevice currentDevice] methodSignatureForSelector:@selector(setOrientation:)]; NSInvocation* invo = [NSInvocation invocationWithMethodSignature:sig]; [invo setTarget:[UIDevice currentDevice]]; [invo setSelector:@selector(setOrientation:)]; [invo setArgument:&orientationPortrait atIndex:2]; [invo invoke]; } }
这适用于iOS7,强制自动旋转到肖像。
//In your viewController.m #import <objc/message.h> // for autorotate viewController to portraid - (void)viewWillAppear:(BOOL)animated { UIInterfaceOrientation orientationStatusBar =[[UIApplication sharedApplication] statusBarOrientation]; switch (orientationStatusBar) { case UIInterfaceOrientationPortrait:break; case UIInterfaceOrientationLandscapeLeft: objc_msgSend([UIDevice currentDevice], @selector(setOrientation:), UIInterfaceOrientationPortrait); break; case UIInterfaceOrientationLandscapeRight: objc_msgSend([UIDevice currentDevice], @selector(setOrientation:), UIInterfaceOrientationPortrait); break; default: break; } } // this permit autorotate - (BOOL) shouldAutorotate { // this lines permit rotate if viewController is not portrait UIInterfaceOrientation orientationStatusBar =[[UIApplication sharedApplication] statusBarOrientation]; if (orientationStatusBar != UIInterfaceOrientationPortrait) { return YES; } //this line not permit rotate is the viewController is portrait return NO; }
注:我在我的应用程序中实现了这个选项,但可能会被苹果拒绝(奥斯汀2012年10月编辑谢尔盖K.的评论)。
苹果在ios6中以编程方式改变设备方向相当困难( 特意介绍你)。
据我所知,要实现你所要求的唯一方法就是模拟设备方向的变化。
使用setTransform
旋转UIView
并重新应用它自己的框架可以得到想要的结果。
[YourView setTransform:CGAffineTransformMakeRotation(1.57)]; [YourView setFrame:CGRectMake(0, 0, YourView.frame.size.width, YourView.frame.size.height)];
而当设备的物理方向改变时,我们可以撤销转换。
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { [YourView setTransform:CGAffineTransformMakeRotation(0)]; [YourView setFrame:CGRectMake(0, 0, YourView.frame.size.width, YourView.frame.size.height)]; }
if (self.interfaceOrientation != UIInterfaceOrientationLandscapeRight) { // http://stackoverflow.com/questions/181780/is-there-a-documented-way-to-set-the-iphone-orientation // http://openradar.appspot.com/radar?id=697 // [[UIDevice currentDevice] setOrientation: UIInterfaceOrientationLandscapeRight]; // Using the following code to get around apple's static analysis... [[UIDevice currentDevice] performSelector:NSSelectorFromString(@"setOrientation:") withObject:(id)UIInterfaceOrientationLandscapeRight]; }
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { // Return YES for supported orientations return NO; }
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { return interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown ; }
这适用于Xcode 6&5。
- (BOOL)shouldAutorotate {return YES;} - (NSUInteger)supportedInterfaceOrientations {return (UIInterfaceOrientationMaskPortrait);}