Morris_ 2019.04.11

前面有总结过一些在开发中遇到的屏幕旋转的基础知识。

一、设置应用支持的转屏方向

设置方式

00x1

在TARGET->General->Deployment Info->Device Orientations下,可设置App支持的屏幕旋转方向。

这里的设置会同步到应用的plist文件中。

00x2

苹果也提供了代码设置app支持的转屏方式的Api:

- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {return UIInterfaceOrientationMaskAllButUpsideDown;
}

这个Api是UIApplicationDelegate中的一个方法,我们在AppDelegate.m中实现此协议方法即可。

区别比较

按照00x1设置后,如果代码中又使用了00x2,则00x2会覆盖00x1的设置。但是对于闪屏的方向设置,00x2的方式是无效的,00x1的设置方式确是有效的。可以理解为,应用在进入时,先读取了plist文件中的屏转设置,然后按照plist文件中的设置进行闪屏的展示,程序执行进AppDelegate.m中时,通过00x2中的Api又获取了一次应用所支持的屏转设置,所以闪屏支持的屏幕旋转设置,必须用00x1的方式设置,00x2的设置是无效的,进入应用后应用支持的转屏方式两种方式都可以。

小结

设置闪屏支持的转屏方式,只能使用00x1的方式,00x2的方式是无效的。

如果不使用代码,直接使用00x1的方式,是可行的。

如果既使用00x1的方式,也使用了代码设置,则00x1的方式设置了闪屏支持的旋转方向,00x2的方式设置了进入应用后界面支持的旋转方向。当然个别界面可以单独设置其支持的旋转方向。

二、设置某个界面支持的转屏方向

有必要了解一下苹果提供的UIViewController的分类UIViewControllerRotation。

// To make it more convenient for applications to adopt rotation, a view controller may implement the below methods. Your UIWindow's frame should use [UIScreen mainScreen].bounds as its frame.
@interface UIViewController (UIViewControllerRotation)...略- (BOOL)shouldAutorotate NS_AVAILABLE_IOS(6_0) __TVOS_PROHIBITED;
- (UIInterfaceOrientationMask)supportedInterfaceOrientations NS_AVAILABLE_IOS(6_0) __TVOS_PROHIBITED;
// Returns interface orientation masks.
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation NS_AVAILABLE_IOS(6_0) __TVOS_PROHIBITED;...略@end

需要注意一下我们经常用到的设置某个controller支持的屏转方向的三个方法。

- (BOOL)shouldAutorotate
{return YES;//设置当前controller是否支持重力感应,即是否可以转屏
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{return UIInterfaceOrientationMaskAllButUpsideDown;//设置支持的转屏方向
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{return UIInterfaceOrientationPortrait;//设置初始的屏幕方向
}

在iOS开关中屏幕旋转(一)中,有说道present出来的视图和push出来的视图的转屏设置有些区别的,在这里重新说明一下,实际上在本质上是没有什么区别的。
push出来的视图的转屏方式,不是看push出来的controller里的设置,而是由controller所在的navigationController所决定的,navigationController是继承自UIViewController的。本质上,不管push出来多少个视图控制器,显示还是在navigationController下的,所以push出来的视图控制器的转屏方式取决于他的navigationController。

navigationController下的子控制器的转屏方向设置不取决于自己,取决于当前所在的navigationController,因为navigationController是继承于UIViewController的,所以在navigationController里进行转屏设置也是有效的。

为了方便不同界面的转屏设置,我们可以在BaseViewController中添加一个属性orientation,系统的UIViewController有一个属性interfaceOrientation,但是是只读的,不能设置。

@property(nonatomic,readonly) UIInterfaceOrientation interfaceOrientation NS_DEPRECATED_IOS(2_0,8_0) __TVOS_PROHIBITED;

我们可以复写这个属性或者重新写一个UIInterfaceOrientation类型的属性。

@interface BaseViewController : UIViewController@property (nonatomic) UIInterfaceOrientation interfaceOrientation;@end

设置初始默认值,并设置默认不支持转屏,在需要支持转屏的界面单独设置,也可以添加一个是否支持转屏的BOOL类型的属性。

@implementation BaseViewController- (instancetype)init {if (self = [super init]) {_interfaceOrientation = UIInterfaceOrientationPortrait;}return self;
}- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {_interfaceOrientation = UIInterfaceOrientationPortrait;}return self;
}- (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view.}- (BOOL)shouldAutorotate {return NO;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {return UIInterfaceOrientationMaskAllButUpsideDown;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {return _interfaceOrientation;
}@end

那么有个问题,有navigationController下的控制器,这样设置是无效的,因为navi下的控制器的转屏取决于当前的nav,而不是子控制器。如果在navigationController下有A和B两个controller,A不支持旋转,B需要支持旋转,这怎么处理?在进入A页面的时候设置navi的转屏方式为不可旋转,进入B页面的时候设置为可旋转,原则上这样可以解决这个需求。那么是不是也要给navi写一个类似的属性呢,给navi也写一个这样的属性来控制问题能解决,但是这样就很麻烦。

有没有什么更简单使用的方法呢?

给UIViewController扩展一个设置屏幕旋转方向的属性orientation和一个是否支持屏幕旋转的属性, 注意尽量不要和系统的属性重名,以免覆盖系统提供的功能。

@interface UIViewController (Rotation)//是否支持重力感应 注意不要和系统的shouldAutorotate属性重名,以免覆盖系统提供的功能
@property (nonatomic) BOOL autoRotate;//方向 注意尽量不要和系统的interfaceOrientation属性重名,以免覆盖系统提供的功能
@property (nonatomic) UIInterfaceOrientation orientation;@end
#import "UIViewController+Rotation.h"
#import <objc/runtime.h>static NSString const *kUIViewControllerRotationKey = @"UIViewControllerRotationKey";
static NSString const *kUIViewControllerAutoRotateKey = @"UIViewControllerAutoRotateKey";//为了和系统的分类UIViewController (UIViewControllerRotation)冲突,分类命名为Rotation
@implementation UIViewController (Rotation)- (void)setOrientation:(UIInterfaceOrientation)orientation {NSNumber *number = [NSNumber numberWithInteger:orientation];objc_setAssociatedObject(self, &kUIViewControllerRotationKey, number, OBJC_ASSOCIATION_RETAIN);//注意这里不能用OBJC_ASSOCIATION_ASSIGN
}
- (UIInterfaceOrientation)orientation {NSNumber *number = objc_getAssociatedObject(self, &kUIViewControllerRotationKey);if (number) {return [number integerValue];}return UIInterfaceOrientationUnknown;
}- (void)setAutoRotate:(BOOL)autoRotate {NSNumber *number = [NSNumber numberWithBool:autoRotate];objc_setAssociatedObject(self, &kUIViewControllerAutoRotateKey, number, OBJC_ASSOCIATION_RETAIN);
}
- (BOOL)autoRotate {NSNumber *number = objc_getAssociatedObject(self, &kUIViewControllerAutoRotateKey);if (number) {return [number boolValue];}return YES;
}@end

这样就可以随心所欲的使用这两个属性进行对屏幕旋转的设置了。

- (BOOL)shouldAutorotate {return self.autoRotate;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {return UIInterfaceOrientationMaskLandscape;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {return self.orientation;
}

二、关于强制转屏的补充

在iOS开关中屏幕旋转(一)中国有提到过强转屏。

需要注意的是,只有在支持重力感应的情况下才能使用强制转屏方法,否则是转不了的。有些应用是不支持重力感应,但是支持某些界面用户手动去切换全屏。这种需求就需要我们在强制转屏前将autoRotate属性设置为YES,并同时需要实现支持重力感应的方法,手动切换全屏才会有效,或者使用其他的全屏方法。

- (void)rotateScreen:(UIInterfaceOrientation)orientation
{//转屏时,先设置支持重力感应,否则此方法无效self.navigationController.autoRotate = YES;if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]){NSNumber *num = [[NSNumber alloc] initWithInt:orientation];[[UIDevice currentDevice] performSelector:@selector(setOrientation:) withObject:(id)num];[UIViewController attemptRotationToDeviceOrientation];}SEL selector=NSSelectorFromString(@"setOrientation:");NSInvocation *invocation =[NSInvocation invocationWithMethodSignature:[UIDevice instanceMethodSignatureForSelector:selector]];[invocation setSelector:selector];[invocation setTarget:[UIDevice currentDevice]];int val = orientation;[invocation setArgument:&val atIndex:2];[invocation invoke];self.navigationController.autoRotate = NO;self.navigationController.orientation = orientation;
}
-(BOOL)shouldAutorotate
{return self.autoRotate;
}

如上设置,不支持重力感应,但是支持用户手动切换屏幕旋转,只支持手动全屏的需求时,这样处理。

Demo

iOS开发中屏幕旋转(一)
iOS开发中屏幕旋转(二)

iOS开发中屏幕旋转(二)相关推荐

  1. iOS开发中屏幕旋转(一)

    Morris_ 2018.11.24 前言 最近做一个关于在线视频互动的iPad项目,部分界面只要横屏,部分界面可以横竖屏转换.看了看别家做的项目,有些是只做竖/横屏,有些是支持了横竖屏转换,在iPa ...

  2. IOS(iphone,ipad,itouch)开发 之 屏幕旋转

    关于IOS开发中屏幕旋转的问题. 看过很多大牛的文章,都写过类似的,这里我只写一下常用的几个函数的具体用法. 首先是 - (BOOL)shouldAutorotateToInterfaceOrient ...

  3. iOS开发中经常用的实用代码合集

    iOS开发中经常用的实用代码合集 本文整理了,在iOS开发中我们所遇到一些开发问题的技巧类的代码,让你在开发过程中避免了很多弯路,希望能给你的开发带来帮助和启发. 1.判断邮箱格式是否正确的代码: / ...

  4. (翻译)开始iOS 7中自动布局教程(二)

     (翻译)开始iOS 7中自动布局教程(二) 这篇教程的前半部分被翻译出来很久了,我也是通过这个教程学会的IOS自动布局.但是后半部分(即本篇)一直未有翻译,正好最近跳坑翻译,就寻来这篇教程,进行 ...

  5. iOS开发中常用的方法

    iOS开发中常用的方法 系统弹窗: 过期方法: UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"确认报价" ...

  6. iOS 开发中的 Flux 架构模式

    本文讲的是iOS 开发中的 Flux 架构模式, 在半年前,我开始在 PlanGrid iOS 应用程序中采用 Flux 架构(开发).这篇文章将会讨论我们从传统的 MVC 转换到Flux的动机,同时 ...

  7. iOS开发中一些有用的小代码

    1.判断邮箱格式是否正确的代码: //利用正则表达式验证 -(BOOL)isValidateEmail:(NSString *)email { NSString *emailRegex = @&quo ...

  8. iOS开发中的神兵利器 [实战系列]-李发展-专题视频课程

    iOS开发中的神兵利器 [实战系列]-11758人已学习 课程介绍         - 140节课程讲解GitHub中近百个过千star的iOS热门开源项目 - 市面上唯一大规模讲解热门的iOS开源项 ...

  9. iOS开发中遇到的一些问题及解决方案【转载】

    iOS开发中遇到的一些问题及解决方案[转载] 2015-12-29 [385][scrollView不接受点击事件,是因为事件传递失败] // //  MyScrollView.m //  Creat ...

最新文章

  1. oracle游标理解,oracle游标的使用方法
  2. 文巾解题 595. 大的国家
  3. VTK:平面源用法实战
  4. Java 8 CompletableFuture
  5. 第三次学JAVA再学不好就吃翔(part85)--静态导入
  6. en结尾的单词_以en结尾的英语单词
  7. axios发送post数据后台收不到_使用axios post 提交数据,后台获取不到
  8. 1.10 编程基础之简单排序 03 成绩排序 3分 python
  9. A股股票交易如何计算
  10. 脱壳--00.aspack.exe
  11. SpringUtil 工具类
  12. 如何在iPhone和iPad上的Safari中在网页上查找文本
  13. mysql57配置教程
  14. c 语言让电脑自动关机,C语言编写简单的定时关机程序
  15. 数据库基础_关系与关系模式
  16. 成都盛铭轩:怎么打造产品差异化
  17. Maven — maven filtering OTS parsing error incorrect file size in WOFF head 产生原因及两种解决方案
  18. maven详解2020
  19. 测回角值计算用计算机,用测回法观测水平角,若半测回角值计算时右目标读数小于左目标读数,则应()。...
  20. 完美解决win10不认移动硬盘和U盘的问题

热门文章

  1. Cadence: 各软件业务
  2. 《商君列传第八》–读书总结
  3. 【Android 进程保活】应用进程拉活 ( 应用进程拉活简介 | 广播拉活 | 显示广播与隐式广播 | 全家桶拉活 )
  4. python中abs和fabs的区别_Python - abs vs fabs
  5. Java实现 LeetCode 93 复原IP地址
  6. 第六章 姜小白当机立断逃莒国 姜诸儿瓜期不代终遇鬼
  7. 如何看待用户反馈意见
  8. guzzle/guzzle 日常使用
  9. Git问题Everything up-to-date正确解决方法
  10. 使用开源人脸特征提取器进行脸部颜值评分