您的位置:首页 > 产品设计 > UI/UE

ios的UIViewController中设置强制横屏

2017-03-21 14:33 127 查看
最近有个需求需要在webview加载的一个签字页面设置强制横屏,因为如果竖屏签字的话,名字是从上到下的,这里总结一下相关的知识和遇到的问题。

因为整个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!!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: