ios的UIViewController中设置强制横屏
2017-03-21 14:33
127 查看
最近有个需求需要在webview加载的一个签字页面设置强制横屏,因为如果竖屏签字的话,名字是从上到下的,这里总结一下相关的知识和遇到的问题。
因为整个app里面只有这个签字页面需要设置为横屏,别的页面都必须是竖屏的,所以【General】 中的【Device Orientation】设置为只支持竖屏
然后在Controller的viewDidLoad中注册通知
这里用到了两个自己定义的属性canRotate和isLandscape,分别表示是否允许改变朝向和是否横屏,收到通知以后的方法如下:
收到H5调用的时候:
做到这里以后,当H5页面调用原生的方法通知app需要横屏的时候,把设备横过来以后页面就会设置为强制横屏了,但是如果没有把设备横过来,就不会设置为强制横屏,因为通知方法没有调用。
解决这个问题的方法如下:
到此就可以正常的实现在UIViewController中实现强制横屏了。
下面是遇到的问题总结:
1.因为这个页面是没有导航控制器的,但是原来的代码里面有一个基类实现了横竖屏切换,所以我最开始的做法是给这个Controller加了一个导航控制器,然后在viewWillAppear中将导航栏隐藏,前面确实也没有发现什么问题,但是后面另一个同事测出一个问题,在签字页面上下左右摇动设备的时候,程序闪退了…. ,错误日志如下:
看这个log基本可以确认是supportedInterfaceOrientations方法的问题,但是这里不管设置成什么程序都会崩溃(BaseNavigationController和UIViewController中都有设置,BaseNavigationController中设置的是调用当前显示的ViewController的supportedInterfaceOrientations方法),研究了半天还是不知道为什么会崩溃,所以不得已还是用上面的方法实现了这个需求,有知道原因的大神还请评论指点一下,thanks!!
因为整个app里面只有这个签字页面需要设置为横屏,别的页面都必须是竖屏的,所以【General】 中的【Device Orientation】设置为只支持竖屏
然后在Controller的viewDidLoad中注册通知
//注册Device Orientation通知 self.canRotate = NO; self.isLandscape = NO; [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceOrientationDidChange) name:UIDeviceOrientationDidChangeNotification object:nil];
这里用到了两个自己定义的属性canRotate和isLandscape,分别表示是否允许改变朝向和是否横屏,收到通知以后的方法如下:
- (void)deviceOrientationDidChange { if (_canRotate) { if([UIDevice currentDevice].orientation == UIDeviceOrientationPortrait && !_isLandscape) { [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait]; [self orientationChange:NO]; //注意: UIDeviceOrientationLandscapeLeft 与 UIInterfaceOrientationLandscapeRight } else if ([UIDevice currentDevice].orientation == UIDeviceOrientationLandscapeLeft &&_isLandscape) { [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight]; [self orientationChange:YES]; } } }
- (void)orientationChange:(BOOL)landscapeRight { _canRotate = NO; CGFloat width = self.view.frame.size.width; CGFloat height = self.view.frame.size.height; if (landscapeRight) { [UIView animateWithDuration:0.2f animations:^{ self.view.transform = CGAffineTransformMakeRotation(M_PI_2); self.view.bounds = CGRectMake(0, 0, height, width); }]; } else { [UIView animateWithDuration:0.2f animations:^{ self.view.transform = CGAffineTransformMakeRotation(0); self.view.bounds = CGRectMake(0, 0, width, height); }]; } }
收到H5调用的时候:
- (void)registCrossScreen { __weak typeof(self) weakself = self; [_webViewBridge registerHandler:@"crossScreen" handler:^(id data, WVJBResponseCallback responseCallback) { NSString *str = [NSString stringWithFormat:@"%@",data]; if ([str isEqualToString:@"1"]) { weakself.canRotate = YES; weakself.isLandscape = YES; [weakself interfaceOrientation:UIInterfaceOrientationLandscapeRight]; } else { weakself.canRotate = YES; weakself.isLandscape = NO; [weakself interfaceOrientation:UIInterfaceOrientationPortrait]; } }]; }
做到这里以后,当H5页面调用原生的方法通知app需要横屏的时候,把设备横过来以后页面就会设置为强制横屏了,但是如果没有把设备横过来,就不会设置为强制横屏,因为通知方法没有调用。
解决这个问题的方法如下:
- (void)interfaceOrientation:(UIInterfaceOrientation)orientation { if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) { 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]; } }
到此就可以正常的实现在UIViewController中实现强制横屏了。
下面是遇到的问题总结:
1.因为这个页面是没有导航控制器的,但是原来的代码里面有一个基类实现了横竖屏切换,所以我最开始的做法是给这个Controller加了一个导航控制器,然后在viewWillAppear中将导航栏隐藏,前面确实也没有发现什么问题,但是后面另一个同事测出一个问题,在签字页面上下左右摇动设备的时候,程序闪退了…. ,错误日志如下:
Date/Time: 2017-03-20 18:11:29.1162 +0800 Launch Time: 2017-03-20 18:10:45.1219 +0800 OS Version: iPhone OS 10.2.1 (14D27) Report Version: 104 Exception Type: EXC_CRASH (SIGABRT) Exception Codes: 0x0000000000000000, 0x0000000000000000 Exception Note: EXC_CORPSE_NOTIFY Triggered by Thread: 0 Application Specific Information: abort() called Filtered syslog: None found Last Exception Backtrace: 0 CoreFoundation 0x18a6011b8 __exceptionPreprocess + 124 1 libobjc.A.dylib 0x18903855c objc_exception_throw + 56 2 CoreFoundation 0x18a601100 +[NSException raise:format:] + 116 3 UIKit 0x1905243bc -[UIViewController __supportedInterfaceOrientations] + 912 4 UIKit 0x19052d680 -[UIViewController __withSupportedInterfaceOrientation:apply:] + 52 5 UIKit 0x19052d5f8 -[UIViewController setInterfaceOrientation:] + 140 6 UIKit 0x19052c0a0 -[UIViewController viewDidMoveToWindow:shouldAppearOrDisappear:] + 1152 7 UIKit 0x1904ac090 -[UIView(Internal) _didMoveFromWindow:toWindow:] + 1352 8 UIKit 0x1904ab2c4 __45-[UIView(Hierarchy) _postMovedFromSuperview:]_block_invoke + 156 9 Foundation 0x18b05ad10 -[NSISEngine withBehaviors:performModifications:] + 168 10 UIKit 0x1904ab138 -[UIView(Hierarchy) _postMovedFromSuperview:] + 820 11 UIKit 0x1904b7018 -[UIView(Internal) _addSubview:positioned:relativeTo:] + 1788 12 UIKit 0x1904b6904 -[UIView(Hierarchy) addSubview:] + 828 13 UIKit 0x19092a6a8 -[_UIAlertControllerPresentationController presentationTransitionWillBegin] + 216 14 UIKit 0x1907fff3c __71-[UIPresentationController _initViewHierarchyForPresentationSuperview:]_block_invoke + 1988 15 UIKit 0x1907fdc88 __56-[UIPresentationController runTransitionForCurrentState]_block_invoke + 460 16 UIKit 0x190740fdc _runAfterCACommitDeferredBlocks + 292 17 UIKit 0x190732d50 _cleanUpAfterCAFlushAndRunDeferredBlocks + 560 18 UIKit 0x1904a20b4 _afterCACommitHandler + 168 19 CoreFoundation 0x18a5ae0c0 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 32 20 CoreFoundation 0x18a5abcf0 __CFRunLoopDoObservers + 372 21 CoreFoundation 0x18a5ac180 __CFRunLoopRun + 1024 22 CoreFoundation 0x18a4da2b8 CFRunLoopRunSpecific + 444 23 GraphicsServices 0x18bf8e198 GSEventRunModal + 180 24 UIKit 0x19051a7fc -[UIApplication _run] + 684 25 UIKit 0x190515534 UIApplicationMain + 208 26 honeycomb 0x1001757d4 0x100060000 + 1136596 27 libdyld.dylib 0x1894bd5b8 start + 4
看这个log基本可以确认是supportedInterfaceOrientations方法的问题,但是这里不管设置成什么程序都会崩溃(BaseNavigationController和UIViewController中都有设置,BaseNavigationController中设置的是调用当前显示的ViewController的supportedInterfaceOrientations方法),研究了半天还是不知道为什么会崩溃,所以不得已还是用上面的方法实现了这个需求,有知道原因的大神还请评论指点一下,thanks!!
相关文章推荐
- iOS设置某个界面强制横屏,进入就横屏
- iOS不勾选设置,实现某个界面强制横屏
- iOS界面设置竖屏,个别界面强制横屏
- 【IOS学习】设置某个界面强制横屏,进入就横屏的几种方法
- iOS 强制竖屏或是横屏 (代码设置后仍无效的问题)
- iOS设置某个界面强制横屏,进入就横屏竖屏
- iOS设置某个界面强制横屏,进入就横屏
- 怎么强制一个UIViewController页面从竖屏进入横屏
- iOS设置某个界面强制横屏,进入就横屏
- Android强制设置横屏或竖屏
- UIViewController的生命周期及iOS程序执行顺序
- iOS UIViewController 对内存警告的处理经验 by bishop
- iOS:关于UIViewController的初始化
- iOS UIViewController 使用要点
- IOS view在UIViewController中的生命周期
- Android 强制设置横屏或竖屏 设置全屏
- Android去掉标题,强制设置横屏或竖屏
- iOS 给一个uiview设置shadow
- 在IOS应用中从竖屏模式强制转换为横屏模式
- Android全屏和强制横屏竖屏设置