最近有个需求需要在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!!
在iOS应用中,仅让WebView加载的签字页面强制横屏,其他页面保持竖屏。设置【General】的【Device Orientation】为竖屏,并在ViewController的`viewDidLoad`中监听通知。通过自定义属性`canRotate`和`isLandscape`控制屏幕方向。在接收到H5通知后调整屏幕方向。若设备未实际横置,页面不会横屏。解决该问题需要在设备旋转前设置横屏。测试过程中遇到程序因`supportedInterfaceOrientations`方法崩溃的问题,尚未找到原因。
1534

被折叠的 条评论
为什么被折叠?



