问答 - 如何强制设备方向在横向和纵向之间旋转
Q&A - How to force device orientation to rotate between landscape and portrait
I'm posting this in Q&A style as there are currently a few posts on
S/O with similar questions and answers that aren't perfectly correct
for all use cases. They typically suffice OP's one specific use case
but are bad for people coming to the site searching for a general-use
answer and lead to hours of frustrated debugging, as I just
experienced. (And in doing so scourged through all of Whosebug's
resources to find that this question (and its answer) had not been
officially asked anywhere except in comments on other posts).
问:如何强制我的应用在纵向和横向模式之间随意切换?
虽然有许多微小的片段允许这样做,但它们会以各种无法预料的方式失败。
例如:
1) 您可以旋转屏幕 UI(不是设备方向),但是如果您截屏或显示 iOS 本机内容(例如弹出警报),它们将以错误的方式定向。
2) 如果您将 orientation
键设置为您想要的方向 UI 并不总是在之后(或根本没有)自动更新。
3) 如果您只是手动执行此操作并手动更新 UI,其他 VC 可能仍会篡改方向,而不是 'locked in'。
4) 如果您手动更新设备方向并刷新 UI,添加新的 ViewController.view 将翻转宽度和高度,因为设备设置尚未更新,即使 [=34] =] 有,在更新这些属性(UI设备尺寸)之前,您必须等待一段未知的时间(0 到 1 秒之间)才能完成旋转动画。
等
我下面的回答解决了在搜索各种 SO 线程时发现的所有潜在问题。
甲:
添加到AppDelegate.h
@property () BOOL landscape;
添加到AppDelegate.m
-(UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
if (self.landscape) {
return UIInterfaceOrientationMaskLandscapeRight;
} else {
return UIInterfaceOrientationMaskPortrait;
}
}
-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
if (self.landscape) {
return UIInterfaceOrientationLandscapeRight;
} else {
return UIInterfaceOrientationPortrait;
}
}
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
if (self.landscape) {
return (UIInterfaceOrientationLandscapeRight);
} else {
return (UIInterfaceOrientationPortrait);
}
}
-(NSUInteger)supportedInterfaceOrientations {
if (self.landscape) {
return UIInterfaceOrientationLandscapeRight;
} else {
return UIInterfaceOrientationPortrait;
}
}
-(BOOL)shouldAutorotate {
return NO;
}
添加到您的VC.m
-(void)setLandscape:(BOOL)landscape {
AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
appDelegate.landscape = landscape;
if (landscape) {
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight];
[[UIDevice currentDevice] setValue:value forKey:@"orientation"];
} else {
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
[[UIDevice currentDevice] setValue:value forKey:@"orientation"];
}
[UINavigationController attemptRotationToDeviceOrientation];//THIS IS THE MOST IMPORTANT LINE IN HERE AND EVERYONE AND ALL SAMPLE CODE LEAVES IT OUT FOR SOME REASON, DO NOT REMOVE THIS LINE. (Forces UI to update), otherwise this orientation change will randomly fail around 1% of the time as UI doesn't refresh for various unknown reasons.
}
最重要的一行是 [UINavigationController attemptRotationToDeviceOrientation];
,出于某种原因,网络上的每个人、Whosebug、示例代码等都将其遗漏。只需设置 orientation
键将导致它在 98% 的时间内工作,但随机 UI 不会更新或者它会在设置键之前更新并且你会遇到方向错误,这会强制它需要时更新。
I'm posting this in Q&A style as there are currently a few posts on S/O with similar questions and answers that aren't perfectly correct for all use cases. They typically suffice OP's one specific use case but are bad for people coming to the site searching for a general-use answer and lead to hours of frustrated debugging, as I just experienced. (And in doing so scourged through all of Whosebug's resources to find that this question (and its answer) had not been officially asked anywhere except in comments on other posts).
问:如何强制我的应用在纵向和横向模式之间随意切换?
虽然有许多微小的片段允许这样做,但它们会以各种无法预料的方式失败。
例如:
1) 您可以旋转屏幕 UI(不是设备方向),但是如果您截屏或显示 iOS 本机内容(例如弹出警报),它们将以错误的方式定向。
2) 如果您将 orientation
键设置为您想要的方向 UI 并不总是在之后(或根本没有)自动更新。
3) 如果您只是手动执行此操作并手动更新 UI,其他 VC 可能仍会篡改方向,而不是 'locked in'。
4) 如果您手动更新设备方向并刷新 UI,添加新的 ViewController.view 将翻转宽度和高度,因为设备设置尚未更新,即使 [=34] =] 有,在更新这些属性(UI设备尺寸)之前,您必须等待一段未知的时间(0 到 1 秒之间)才能完成旋转动画。
等
我下面的回答解决了在搜索各种 SO 线程时发现的所有潜在问题。
甲:
添加到AppDelegate.h
@property () BOOL landscape;
添加到AppDelegate.m
-(UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
if (self.landscape) {
return UIInterfaceOrientationMaskLandscapeRight;
} else {
return UIInterfaceOrientationMaskPortrait;
}
}
-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
if (self.landscape) {
return UIInterfaceOrientationLandscapeRight;
} else {
return UIInterfaceOrientationPortrait;
}
}
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
if (self.landscape) {
return (UIInterfaceOrientationLandscapeRight);
} else {
return (UIInterfaceOrientationPortrait);
}
}
-(NSUInteger)supportedInterfaceOrientations {
if (self.landscape) {
return UIInterfaceOrientationLandscapeRight;
} else {
return UIInterfaceOrientationPortrait;
}
}
-(BOOL)shouldAutorotate {
return NO;
}
添加到您的VC.m
-(void)setLandscape:(BOOL)landscape {
AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
appDelegate.landscape = landscape;
if (landscape) {
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight];
[[UIDevice currentDevice] setValue:value forKey:@"orientation"];
} else {
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
[[UIDevice currentDevice] setValue:value forKey:@"orientation"];
}
[UINavigationController attemptRotationToDeviceOrientation];//THIS IS THE MOST IMPORTANT LINE IN HERE AND EVERYONE AND ALL SAMPLE CODE LEAVES IT OUT FOR SOME REASON, DO NOT REMOVE THIS LINE. (Forces UI to update), otherwise this orientation change will randomly fail around 1% of the time as UI doesn't refresh for various unknown reasons.
}
最重要的一行是 [UINavigationController attemptRotationToDeviceOrientation];
,出于某种原因,网络上的每个人、Whosebug、示例代码等都将其遗漏。只需设置 orientation
键将导致它在 98% 的时间内工作,但随机 UI 不会更新或者它会在设置键之前更新并且你会遇到方向错误,这会强制它需要时更新。