问题原因: 苹果又给我们挖坑了,iOS 16屏幕旋转报错:[Orientation] BUG IN CLIENT OF UIKIT: Setting UIDevice.orientation is not supported. Please
苹果又给我们挖坑了,iOS 16屏幕旋转报错:[Orientation] BUG IN CLIENT OF UIKIT: Setting UIDevice.orientation is not supported. Please use UIWindowScene.requestGeometryUpdate(_:)
坑:听说xcode 14 和 xcode 13编译出的安装包效果不一,经测试确实如此!还是要打包测试完毕以后再上线哦!
经过实验,以前的方法直接给UIDevice setOrientation: 的方式还是生效的,只不过需要适配一下。
首先我们应该注意到iOS 16新增加了一个方法:setNeedsUpdateOfSupportedInterfaceOrientations
/// Notifies the view controller that a change occurred that affects supported interface orientations or the preferred interface orientation for presentation./// By default, this will animate any changes to orientation. To perfORM a non-animated update, call within `[UIView performWithoutAnimation:]`.- (void)setNeedsUpdateOfSupportedInterfaceOrientations api_AVaiLABLE(ios(16.0));
这和更新状态栏的方法有点像,简单点说就是你想转屏可以,需要通知UIViewController 你已经准备好要转屏的方向了,然后再调用转屏方法即可(转屏方法后面会讲到)。
调用完转屏方法以后,view需要重新更新frame,这时候你会发现获取到的屏幕宽高并不是你要转屏以后的结果。难道是在iOS 16中转屏不及时更新UIScreen的size了? 可能是吧!这里我们就需要自己判断一下到底需要什么样的宽度和高度啦!
据我实验 - (BOOL)shouldAutorotate{} 在iOS 16中不再起效果!不管返回YES还是NO都能转屏!!!反而是需要控制- (UIInterfaceOrientationMask)supportedInterfaceOrientations有效果,神奇不!!
据我实验在iOS 16中转屏的时候,直接获取设备方向:
UIDeviceOrientation orientation = [UIDevice currentDevice].orientation;
将返回UIDeviceOrientationUnknown,是不是神坑!!!!!
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 = UIDeviceOrientationPortrait; [invocation setArgument:&val atIndex:2]; [invocation invoke];}[UIViewController attemptRotationToDeviceOrientation];
当然,据实验所知,iOS 16以后也能用,只不过会有日志警告。如果你用Xcode 14 ,此方案在iOS 16上就不好用了!
if (@available(iOS 16.0, *)) { // setNeedsUpdateOfSupportedInterfaceOrientations 方法是 UIViewController 的方法 [self setNeedsUpdateOfSupportedInterfaceOrientations]; NSArray *array = [[[UIApplication sharedApplication] connectedScenes] allObjects]; UIwindowscene *scene = [array firstObject]; // 屏幕方向 UIInterfaceOrientationMask orientation = isLaunchScreen ? UIInterfaceOrientationMaskLandscape: UIInterfaceOrientationMaskPortrait; UIWindowSceneGeometryPreferencesIOS *geometryPreferencesIOS = [[UIWindowSceneGeometryPreferencesIOS alloc] initWithInterfaceOrientations:orientation]; // 开始切换 [scene requestGeometryUpdateWithPreferences:geometryPreferencesIOS errorHandler:^(NSError * _Nonnull error) { NSLog(@"错误:%@", error); }];}
当然如果你没有升级到Xcode 14,还可以这样写:(据我实验不好用,只能横屏,不能再转到竖屏,不推荐此方案!)
if (@available(iOS 16.0, *)) { void (^errorHandler)(NSError *error) = ^(NSError *error) { NSLog(@"错误:%@", error); };#pragma clang diagnostic push#pragma clang diagnostic ignored "-Warc-performSelector-leaks" SEL supportedInterfaceSelector = NSSelectorFromString(@"setNeedsUpdateOfSupportedInterfaceOrientations"); [self performSelector:supportedInterfaceSelector]; NSArray *array = [[UIApplication sharedApplication].connectedScenes allObjects]; UIWindowScene *scene = (UIWindowScene *)[array firstObject]; Class UIWindowSceneGeometryPreferencesIOS = NSClassFromString(@"UIWindowSceneGeometryPreferencesIOS"); if (UIWindowSceneGeometryPreferencesIOS) { SEL initWithInterfaceOrientationsSelector = NSSelectorFromString(@"initWithInterfaceOrientations:"); UIInterfaceOrientationMask orientation = UIInterfaceOrientationMaskPortrait; id geometryPreferences = [[UIWindowSceneGeometryPreferencesIOS alloc] performSelector:initWithInterfaceOrientationsSelector withObject:@(orientation)]; if (geometryPreferences) { SEL requestGeometryUpdateWithPreferencesSelector = NSSelectorFromString(@"requestGeometryUpdateWithPreferences:errorHandler:"); if ([scene respondsToSelector:requestGeometryUpdateWithPreferencesSelector]) { [scene performSelector:requestGeometryUpdateWithPreferencesSelector withObject:geometryPreferences withObject:errorHandler]; } } }#pragma clang diagnostic pop}
横屏按钮点击事件:
if (@available(iOS 16, *)) { _landscape = YES; [self setNeedsUpdateOfSupportedInterfaceOrientations];}
竖屏按钮点击事件:
if (@available(iOS 16, *)) { _landscape = NO; [self setNeedsUpdateOfSupportedInterfaceOrientations];}
再加一个方法:
- (UIInterfaceOrientationMask)supportedInterfaceOrientations { if (_landscape) { //横屏 return UIInterfaceOrientationMaskLandscape; }else { //竖屏 return UIInterfaceOrientationMaskPortrait; }}
极简单的代码即可完成你想要的效果。
如果你的[self setNeedsUpdateOfSupportedInterfaceOrientations] 没起任何作用,你可以需要在主线程main queue中调用它!
总结完毕!有疑问欢迎下方留言讨论!
GitHub - TheLittleBoy/HXRotationTool: iOS 屏幕旋转工具类,兼容iOS 16,兼容Xcode 13和Xcode 14。
如图:
喜欢的小伙伴就帮忙点个收藏吧~
来源地址:https://blog.csdn.net/xuexixiaoshizhe/article/details/126955521
--结束END--
本文标题: iOS 16适配屏幕旋转强制转屏切换大总结
本文链接: https://www.lsjlt.com/news/393825.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
下载Word文档到电脑,方便收藏和打印~
2024-01-21
2023-10-28
2023-10-28
2023-10-27
2023-10-27
2023-10-27
2023-10-27
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0