在启动时检测界面方向的正确方法是什么?

发布于 2024-10-03 06:34:43 字数 1240 浏览 1 评论 0原文

[问题已更新]

这就是问题所在,我最终将其范围缩小到了这一点。如果您在所有方法中创建一个新的 UIViewController

- (id)init;
- (void)loadView;
- (void)viewDidAppear:(BOOL)animated;
- (void)viewDidLoad;
(...)

标准界面方向是纵向,如果检测到横向模式,它将快速旋转到该方向。然后可以使用以下方法检测到:

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation;

问题是,在 iPad 上,在 loadView(或其他之一)中为当前界面方向准备界面非常困难,因为它只会返回纵向。这会导致一些问题:

1)我希望我的内容以纵向模式重新加载,而不是横向模式。通常我会在 loadView 中放置一个 if 语句。如果处于纵向模式,请重新加载内容。但在这种情况下,它将始终返回纵向,因此始终加载内容。

2)我想在纵向模式下使用“presentPopoverFromRect:inView:permissedArrowDirections:animated:”方法,这样它会在应用程序启动时自动显示弹出菜单。当以纵向模式启动时,这将使应用程序崩溃。原因:“无法从没有窗口的视图中呈现弹出窗口。”。

唯一安全的假设是在“didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation”内,但如果以纵向模式启动,则不会触发此方法。

//----

更新 (15.37)

'UIApplicationWillChangeStatusBarOrientationNotification'

仅当用户从纵向切换到横向(反之亦然)时才会发布。如果界面是问题,那么可以通过观察该通知轻松解决这个问题,

if (UIDeviceOrientationIsPortrait(interfaceOrientation)) {
    // layout subviews for portrait mode
} else {
    // layout subviews for landscape mode
}

但问题是我想知道它在启动时处于哪种模式以确定我是否应该重新加载内容,我无法重新加载内容,当它切换到横向时取消它。

[Question updated]

So here is the problem, I finally narrowed it down to this. If you create a new UIViewController in all methods

- (id)init;
- (void)loadView;
- (void)viewDidAppear:(BOOL)animated;
- (void)viewDidLoad;
(...)

The standard interfaceOrientation is Portrait and if landscape mode is detected it will quickly rotate to that orientation. Which can then be detected using the:

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation;

The problem is that on the iPad, it's quiet difficult to prepare your interface for the current interface orientation within the loadView (or one of the others) as it will only return Portrait. This will cause for a few problems:

1) I want my content to reload in portait mode, but NOT in landscape mode. Normally I would place an if statement in the loadView. If in portrait mode, reload content. But in this case it will always return portrait and thus always loads content.

2) I want to use 'presentPopoverFromRect:inView:permittedArrowDirections:animated:'-method when in portrait mode so it will present the popover menu automaticly when the application starts. This will crash the application when launched in portrait mode. Reason: 'Popovers cannot be presented from a view which does not have a window.'.

The only safe assumption is within 'didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation', but this method will not be fired if it launches in portrait mode.

//----

Update (15.37)

'UIApplicationWillChangeStatusBarOrientationNotification'

Will only be posted when the user swaps from portrait to landscape (or vica versa). If interface was the problem then this can easily be solved with observing for that notification and

if (UIDeviceOrientationIsPortrait(interfaceOrientation)) {
    // layout subviews for portrait mode
} else {
    // layout subviews for landscape mode
}

But the problem is that I want to know in which mode it is at launch to determine rather or not I should reload the content, I can't reload the content and when it swaps to landscape cancel it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

从此见与不见 2024-10-10 06:34:43

尝试[[UIApplication sharedApplication] statusBarOrientation]

Try [[UIApplication sharedApplication] statusBarOrientation].

み青杉依旧 2024-10-10 06:34:43

正确的方法是询问设备其方向,因为视图在技术上没有方向。 ;)

所以你使用 UIDevice 是正确的。从 文档 您可以看到在该信息正确之前,您首先需要生成设备方向通知。然后它将按预期工作。

UIDevice *myDevice = [UIDevice currentDevice];
[myDevice beginGeneratingDeviceOrientationNotifications];
UIDeviceOrientation currentOrientation = [myDevice orientation];
[myDevice endGeneratingDeviceOrientationNotifications];

注意:这将为您提供设备的当前方向。如果当前可见/顶部视图控制器不允许旋转到该方向,您仍然会获得当前设备方向,而不是最顶层视图控制器当前使用的方向。


问题更新后编辑

您是正确的,最顶层视图控制器的方向(对于子视图控制器正确工作)在loadView中始终返回1(即UIInterfaceOrientationPortrait。然而,方法 willRotateToInterfaceOrientation:duration: 随后将立即被调用,并且传递的方向是正确的,因此您应该能够使用该方法。

- (void) willRotateToInterfaceOrientation:(UIInterfaceOrientation)toIfaceOrient
                                 duration:(NSTimeInterval)duration

The proper way is to ask the device for its orientation as a view technically has no orientation. ;)

So you're correct in using UIDevice. From the documentation you can see that you first need to generate device orientation notifications before this information is correct. Then it will work as desired.

UIDevice *myDevice = [UIDevice currentDevice];
[myDevice beginGeneratingDeviceOrientationNotifications];
UIDeviceOrientation currentOrientation = [myDevice orientation];
[myDevice endGeneratingDeviceOrientationNotifications];

Note: This gives you the current orientation of the device. If the currently visible/top view controller did not allow rotation to this orientation, you will nevertheless get the current device orientation, not the one the topmost view controller currently uses.


Edit after question was updated:

You are correct that the orientation for the topmost view controller (worked correctly for subview controllers) always returns 1 (i.e. UIInterfaceOrientationPortrait) in loadView. However the method willRotateToInterfaceOrientation:duration: will immediately afterwards be called, and the orientation passed there is correct, so you should be able to use that method.

- (void) willRotateToInterfaceOrientation:(UIInterfaceOrientation)toIfaceOrient
                                 duration:(NSTimeInterval)duration
ゃ懵逼小萝莉 2024-10-10 06:34:43

我不确定这是否能真正解决我的问题,但查看文档后,我发现了以下内容:

typedef enum {
   UIInterfaceOrientationPortrait           = UIDeviceOrientationPortrait,
   UIInterfaceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown,
   UIInterfaceOrientationLandscapeLeft      = UIDeviceOrientationLandscapeRight,
   UIInterfaceOrientationLandscapeRight     = UIDeviceOrientationLandscapeLeft
} UIInterfaceOrientation;

因此

typedef enum {
   UIDeviceOrientationUnknown,
   UIDeviceOrientationPortrait,
   UIDeviceOrientationPortraitUpsideDown,
   UIDeviceOrientationLandscapeLeft,
   UIDeviceOrientationLandscapeRight,
   UIDeviceOrientationFaceUp,
   UIDeviceOrientationFaceDown
} UIDeviceOrientation;

,由于添加了 FaceUp 和 FaceDown,出于接口原因,查看设备的方向是毫无意义的。因此,从理论上讲,@MarkAdams 正确地提到,在这种情况下 [[UIApplication sharedApplication] statusBarOrientation] 应该用于界面方向。

或者当然 UIViewController 有选项“interfaceOrientation”。

I am not sure if this will actually solve my problem but looking at the documentation I found the following:

typedef enum {
   UIInterfaceOrientationPortrait           = UIDeviceOrientationPortrait,
   UIInterfaceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown,
   UIInterfaceOrientationLandscapeLeft      = UIDeviceOrientationLandscapeRight,
   UIInterfaceOrientationLandscapeRight     = UIDeviceOrientationLandscapeLeft
} UIInterfaceOrientation;

and

typedef enum {
   UIDeviceOrientationUnknown,
   UIDeviceOrientationPortrait,
   UIDeviceOrientationPortraitUpsideDown,
   UIDeviceOrientationLandscapeLeft,
   UIDeviceOrientationLandscapeRight,
   UIDeviceOrientationFaceUp,
   UIDeviceOrientationFaceDown
} UIDeviceOrientation;

So since FaceUp and FaceDown have been added looking at the orientation of the Device is pointless for Interface reasons. Therefor, theoretically, @MarkAdams is right mentioning that in this case [[UIApplication sharedApplication] statusBarOrientation] should be used for the interface orientation.

Or of course the UIViewController has the option 'interfaceOrientation'.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文