iOS小技能:指定某个页面可以旋转屏幕,其余控制器都正常竖屏。

884 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第8天,点击查看活动详情

引言

需求:电子签名

旋转特定屏幕的原理:

  1. 对于任意一个viewController,以info.plist设置的支持横竖屏旋转和当前viewControllerpreferredInterfaceOrientationForPresentation以及supportedInterfaceOrientations三者支持的方向做一个交运算

———————————————— 版权声明:本文为CSDN博主「iOS逆向」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:blog.csdn.net/z929118967/…

/*是否应该自动旋转屏幕**/

- (BOOL)shouldAutorotate{

    return YES;

}

 /*是否支持屏幕旋转并指明旋转方向

supportedInterfaceOrientations作用是屏幕支持的方向有哪些,这个方法返回值是个枚举值UIInterfaceOrientationMask具体值有下面:
typedef NS_OPTIONS(NSUInteger, UIInterfaceOrientationMask) {
    //向上为正方向的竖屏
    UIInterfaceOrientationMaskPortrait = (1 << UIInterfaceOrientationPortrait),
    //向左移旋转的横屏
    UIInterfaceOrientationMaskLandscapeLeft = (1 << UIInterfaceOrientationLandscapeLeft),
    //向右旋转的横屏
    UIInterfaceOrientationMaskLandscapeRight = (1 << UIInterfaceOrientationLandscapeRight),
    //向下为正方向的竖屏
    UIInterfaceOrientationMaskPortraitUpsideDown = (1 << UIInterfaceOrientationPortraitUpsideDown),
    //向左或者向右的横屏
    UIInterfaceOrientationMaskLandscape = (UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight),
    //所有的横竖屏方向都支持
    UIInterfaceOrientationMaskAll = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskPortraitUpsideDown),
    //支持向上的竖屏和左右方向的横屏
    UIInterfaceOrientationMaskAllButUpsideDown = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight),
} __TVOS_PROHIBITED;
**/

- (UIInterfaceOrientationMask)supportedInterfaceOrientations{

    return UIInterfaceOrientationMaskLandscapeLeft;

}

/*

preferredInterfaceOrientationForPresentation 默认的屏幕方向

The interface orientation to use when presenting the view controller.
即当前ViewController必须是通过模态出来的UIViewController(模态带导航的无效)才会调用这个方法


返回值是UIInterfaceOrientation是个枚举值

typedef NS_ENUM(NSInteger, UIInterfaceOrientation) {
    //屏幕方向未知
    UIInterfaceOrientationUnknown            = UIDeviceOrientationUnknown,
    //向上正方向的竖屏
    UIInterfaceOrientationPortrait           = UIDeviceOrientationPortrait,
    //向下正方向的竖屏
    UIInterfaceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown,
    //向右旋转的横屏
    UIInterfaceOrientationLandscapeLeft      = UIDeviceOrientationLandscapeRight,
    //向左旋转的横屏
    UIInterfaceOrientationLandscapeRight     = UIDeviceOrientationLandscapeLeft
} __TVOS_PROHIBITED;
**/ 

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{

    return UIInterfaceOrientationLandscapeLeft;

    

}



  1. 传递子控制器的屏幕旋转属性

I 签名界面为横屏,其余页面为竖屏

1.1 方案一:使用方法交换进行控制旋转,避免控制旋转代码被覆盖(推荐)

+ (void)load {
    Method originAddObserverMethod = class_getInstanceMethod(self, @selector(presentViewController:animated:completion:));
    Method swizzledAddObserverMethod = class_getInstanceMethod(self, @selector(K_presentViewController:animated:completion:));
    method_exchangeImplementations(originAddObserverMethod, swizzledAddObserverMethod);
    
    
    
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            
            NSArray *selStringsArray = @[@"shouldAutorotate",@"supportedInterfaceOrientations",@"preferredInterfaceOrientationForPresentation"];
            
            
            [selStringsArray enumerateObjectsUsingBlock:^(NSString *selString, NSUInteger idx, BOOL *stop) {
                NSString *mySelString = [@"sd_" stringByAppendingString:selString];
                
                Method originalMethod = class_getInstanceMethod(self, NSSelectorFromString(selString));
                Method myMethod = class_getInstanceMethod(self, NSSelectorFromString(mySelString));
                method_exchangeImplementations(originalMethod, myMethod);
            }];
        });
    

}


#pragma mark - ******** 2、【如果用户有打开手机的自动旋转功能 除了签名界面的页面,其余的都是竖屏】:

- (BOOL)sd_shouldAutorotate{
    
    
    return YES;
    

}


- (UIInterfaceOrientationMask)sd_supportedInterfaceOrientations {
    
    return UIInterfaceOrientationMaskPortrait;
}
-(UIInterfaceOrientation)sd_preferredInterfaceOrientationForPresentation{
    
    return UIInterfaceOrientationPortrait;
}



1.2 方案2 :重写UIViewController分类的控制旋转相关方法(不推荐)

- (BOOL)shouldAutorotate {
    return YES;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskPortrait;
}
-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
    return UIInterfaceOrientationPortrait;
}



1.3 案例:采集电子签名

  1. 原理文章:kunnan.blog.csdn.net/article/det…
  2. 功能:采集电子签名,支持签名界面为横屏其余页面都是竖屏、清除重写、灵活控制提示语信息、以及查看商户协议
  3. 核心原理: 只旋转特定的屏幕

下载完整电子签名SDK源码:download.csdn.net/download/u0…

II 其他实现方式

在AppDelegate 中实现以下两个方法

/**
 
 */
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
    if (_allowRotation == 1) {
        return UIInterfaceOrientationMaskAllButUpsideDown;
    }else{
        return (UIInterfaceOrientationMaskPortrait);
    }
}

// 支持设备自动旋转
- (BOOL)shouldAutorotate
{
    if (_allowRotation == 1) {
        return YES;
    }
    return NO;
}

在你要旋转的controller中一开始的地方写这两句就可以了


 
 
 - (void)setupView{
 
 AppDelegate  *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
 
 appDelegate.allowRotation = 1;
 
 }
 
 
 - (void)viewWillDisappear:(BOOL)animated{
 [super viewWillDisappear:animated];
 
 AppDelegate  *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
 
 appDelegate.allowRotation = 0;
 
 }