复杂的多设备定位处理

问题描述 投票:3回答:2

我有一个在iPad和iPhone上运行的通用应用程序。应用程序以.xib文件开始,该文件内置于界面构建器中,该文件充当启动映像。应用程序启动后,会根据应用程序委托中设置的设备大小切换到相应的视图控制器:

CGSize screenSize = [[UIScreen mainScreen] bounds].size;

if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
    if (screenSize.height <= 568.0f) {
        // iPhone 4, 4S, 5, 5C, 5S, SE
        self.viewController = [[iPhoneSmallViewController alloc] init];
    } else {
        // All other iPhones
        self.viewController = [[iPhoneLargeViewController alloc] init];
    }
} else {
    // All iPad models
    self.viewController = [[iPadViewController alloc] init];
}

iPad视图控制器支持所有界面方向(在app目标/主设置页面中设置),但在iPhone上我只允许在视图控制器中限制纵向模式:

- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
    return (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown);
}

这个方法有两个问题:

  1. 如果iPhone水平放置,应用程序仍然以纵向模式加载(根据限制,这一切都很好)但所有测量都在初始化时处于横向状态。 UI元素在侧面伸出,因为它们被测量为横向视图但被放置在肖像上。

我使用窗口的大小通过在ViewDidLoad方法中初始化以下变量来设置视图中的所有内容:

windowSize = [[UIScreen mainScreen] bounds].size;

即使不允许横向模式,Tt也会让我在手机中横向保持横向尺寸。

  1. 如果应用程序最初加载了横向测量,那么我在app delegate中对屏幕尺寸的所有排序都是关闭的,因为我通过测量仅在纵向模式下良好的屏幕宽度来识别iPhone模型。

问题:有没有人能够以优雅和简单的方式处理这个复杂的问题?

一些额外的信息:我使用Xcode 10,支持一直回到iOS9并在Objective C中以编程方式完成所有操作。

p.s:我认为这种方法之前有效,但在iOS 12中已经不再适用了。但我可能错了......

编辑:我提供了我想要完成的图像,所有的帮助将不胜感激。正如我所说,这已经有效了(应用程序已经很老了),但是在最近的iOS版本中,越来越多的越野车越来越需要清理,这是我需要帮助的。

可能解决我的问题的一件事是,如果我可以在launchScreen.xib中基于设备类型以某种方式限制接口方向,因为我认为这是导致iPhone上的错误行为的原因。

enter image description here

objective-c xcode uiinterfaceorientation ios12
2个回答
0
投票

也许这个SO会有所帮助,他们正在检测设备方向,然后旋转视图,看看第一个答案:

Change orientation programmatically with button - iOS

UIInterfaceOrientation currentOrientation = [UIApplication         sharedApplication].statusBarOrientation;
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
[[UIDevice currentDevice] setValue:value forKey:@"orientation"];    
[UIViewController attemptRotationToDeviceOrientation];

这里解释了检测设备的更好方法:iOS detect if user is on an iPad

if ( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad )
{
    return YES; /* Device is iPad */
}

0
投票

我已经试验了好几天了,并找到了解决方案。虽然这可能不是最优雅的方式,但如果有人有更好的解决方案,请随时发布。

  1. 在info.plist中允许所有接口方向很重要,因为我无法根据launchScreen.xib中的设备大小来限制它们。
  2. 创建支持iPad和iPhone的通用启动屏幕。因为info.plist中允许所有接口方向,所以没有限制。
  3. 以下是我在app委托中的当前方法。这不是识别较小的iPhone的最佳方式(我需要的原因...... :),但由于尺寸的不同,这种方法效果很好。

此时,手机可以处于info.plist中设置的四个界面方向中的任意一个,但由于只有小手机具有320宽度,因此很容易捕获它:

// Get screen size
CGSize screenSize = [[UIScreen mainScreen] bounds].size;

// Determine device based on screen dimensions
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
    if ( (screenSize.height == 320.0f) || (screenSize.width == 320.0f) ){
        // iPhone 4, 4S, 5, 5C, 5S, SE
        self.viewController = [[iPhoneSmallViewController alloc] init];
    } else {
        // iPhone 6, 6S, 6P, 6SP, 7, 7P, 8, 8P X, XS, XM, XR
        self.viewController = [[iPhoneLargeViewController alloc] init]; //Same as previous
    }
} else {
    // All iPad models
    self.viewController = [[iPadViewController alloc] init];
}
  1. 限制iPhone视图控制器中的界面方向(所有其他视图控制器将继承我们在info.plist中设置的视图控制器)。

这样做:

- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return (UIInterfaceOrientationMaskPortrait);
}
  1. 我们需要做的另一个技巧是让上面的工作起作用。当窗口第一次加载时,它不会考虑我们添加到视图控制器的限制。这意味着,如果我们在viewDidLoad方法中进行设置,如果设备水平保持,我们将接收横向屏幕尺寸(即使不允许此方向)。一旦viewDidLoad方法结束,将应用限制。

因此,为了防止错误行为,您需要创建一个单独的方法来进行设置(例如postViewDidLoad)并在真正的viewDidLoad结束后调用它:

- (void) viewDidLoad
{
    [super viewDidLoad];

    [self performSelector:@selector(postViewDidLoad) withObject:nil afterDelay:0.0f];
}

在此方法中,您将根据在supportedInterfaceOrientations方法中设置的限制来访问实际屏幕大小。

这基本上就是这样。如果您有多个视图,但都有不同的限制,请按照每个视图中的步骤4和5来正确设置工作流程。

© www.soinside.com 2019 - 2024. All rights reserved.