Сложное управление несколькими устройствами - PullRequest
3 голосов
/ 16 апреля 2019

У меня есть универсальное приложение, работающее как на 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 поддерживает все ориентации интерфейса (заданные в целях приложения / главной странице настройки),но на айфонах я разрешаю только режим портрета, ограниченный в контроллере вида как таковой:

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

У меня есть две проблемы с этим методом:

  1. Если iPhone удерживается горизонтально,приложение по-прежнему загружается в портретном режиме (согласно ограничениям, что все хорошо), но все измерения находятся в альбомной ориентации при инициализации.Элементы пользовательского интерфейса торчат из стороны, потому что они были измерены для ландшафтного вида, но помещены на портрет.

Я использую размер окна, чтобы установить все внутри представления, инициализируя следующую переменную в ViewDidLoadМетод:

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

Tt дает мне горизонтальные размеры в телефоне удерживается горизонтально, хотя ландшафтный режим не допускается.

Если приложение изначально загружается с альбомными измерениями, все мои сортировки размеров экрана в делегате приложения отключены, поскольку я определяю модели iPhone по измерению ширины экрана, которая подходит только в портретном режиме.

Вопрос: есть ли у кого-нибудь способ решить эту сложную проблему элегантным и простым способом?

Некоторая дополнительная информация: я использую Xcode 10, полностью поддерживаю iOS9 и все делаю программно в Objective C.

ps: я думаю, что этот метод работал раньше, но больше не работает в iOS 12. Но я могу ошибаться ...

Редактировать: я предоставляю изображение того, чего я хочу достичь, и всеПомощь будет принята с благодарностью.Как я уже сказал, это работало и раньше (приложение довольно старое), но в последних выпусках iOS стало все более глючно и отчаянно требуется очистка, с чем мне нужна помощь.

Одна вещь, которая может решить моюпроблема заключается в том, если бы я мог каким-то образом ограничить ориентацию интерфейса в зависимости от типа устройства в файле launchScreen.xib, поскольку я считаю, что именно это приводит к неправильному поведению на iPhone.

enter image description here

Ответы [ 2 ]

0 голосов
/ 22 апреля 2019

Я экспериментировал с этим в течение нескольких дней и разработал решение. Хотя это, вероятно, не самый элегантный способ сделать это, поэтому, если у кого-то есть лучшее решение, пожалуйста, не стесняйтесь его опубликовать.

  1. Важно разрешить все ориентации интерфейса в файле info.plist, поскольку я не смог ограничить их в зависимости от размера устройства в файле launchScreen.xib.

  2. Создайте универсальный экран запуска, который поддерживает как iPad, так и iPhone. Поскольку в info.plist разрешены все ориентации интерфейса, это не будет иметь никаких ограничений.

  3. Ниже мой текущий метод в делегате приложения. Это не лучший способ определить меньшие айфоны (которые мне нужны по причинам ... :), но из-за различий в размерах это работает довольно хорошо.

На данный момент телефон может иметь любую из четырех ориентаций интерфейса, установленных в 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];
}

В этом методе вы получите доступ к реальному размеру экрана в соответствии с вашими ограничениями, которые вы установили в методе selectedInterfaceOrientations.

И это в основном все. Если у вас несколько представлений с разными ограничениями, просто выполните шаги 4 и 5 в каждом из них, чтобы правильно настроить рабочий процесс.

0 голосов
/ 22 апреля 2019

Может быть, это ТА будет полезно, они определяют ориентацию устройства, а затем поворачивают вид, смотрят первый ответ:

Программно меняйте ориентацию с помощью кнопки - iOS

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

Лучший способ обнаружить устройство объясняется здесь: iOS определяет, находится ли пользователь на iPad

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