Разные классы размера для портретных и ландшафтных режимов iPad с ограничениями

Я нашел этот вопрос, и я попытался реализовать решение, которое было предоставлено. Однако я столкнулся с проблемой.

У моего контроллера начального представления есть два вида контейнеров, у которых есть свой собственный контроллер вида. Я создал контроллер корневого представления, который назначен контроллеру начального представления. Код в этом классе выглядит следующим образом.

class RootViewController: UIViewController {

var willTransitionToPortrait: Bool!
var traitCollection_CompactRegular: UITraitCollection!
var traitCollection_AnyAny: UITraitCollection!

override func viewDidLoad() {
    super.viewDidLoad()
    setupReferenceSizeClasses()
    // Do any additional setup after loading the view.
}

override func viewWillAppear(animated: Bool) {
    willTransitionToPortrait = self.view.frame.size.height > self.view.frame.size.width
}

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
    willTransitionToPortrait = size.height > size.width
}

func setupReferenceSizeClasses(){
    let traitCollection_hCompact = UITraitCollection(horizontalSizeClass: .Compact)
    let traitCollection_vRegular = UITraitCollection(verticalSizeClass: .Regular)
    traitCollection_CompactRegular = UITraitCollection(traitsFromCollections: [traitCollection_hCompact, traitCollection_vRegular])

    let traitCollection_hAny = UITraitCollection(horizontalSizeClass: .Unspecified)
    let traitCollection_vAny = UITraitCollection(verticalSizeClass: .Unspecified)
    traitCollection_AnyAny = UITraitCollection(traitsFromCollections: [traitCollection_hAny, traitCollection_vAny])
}

override func overrideTraitCollectionForChildViewController(childViewController: UIViewController) -> UITraitCollection? {
    let traitCollectionForOverride = ((willTransitionToPortrait) != nil) ? traitCollection_CompactRegular : traitCollection_AnyAny

    return traitCollectionForOverride;
}

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

ландшафтный режим портретный режим

Когда я не назначу rootviewcontroller, это будет выглядеть так ландшафтный режим портретный режим

Пока он выглядит в портретном режиме портретный режим, как он должен выглядеть

Кто-нибудь знает, что здесь может быть неправильным? Почему он не меняет класс размера, как хотелось бы.

ИЗМЕНИТЬ Как @Muhammad Yawar Ali спросили здесь скриншоты с позиции всех классов размера, которые я установил. У меня нет предупреждений или ошибок о любых ограничениях, поэтому эти скриншоты содержат обновленные представления.

введите описание изображения здесь введите описание изображения здесь

Надеюсь, это показывает все, что нужно.

EDIT: по какой-то причине я не могу поставить все скриншоты

Ответ 1

На viewWillTransitionToSize вам нужно вызвать также супер, чтобы передать событие следующему ответчику (ваш rootviewcontroller)...

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
    willTransitionToPortrait = size.height > size.width
}

Ответ 2

Поймите, что это более двух лет, но...

Я просто столкнулся с тем, что, по моему мнению, является аналогичной проблемой. Что вы можете забыть, так это то, что "overrideTraitCollectionForChildViewController" переопределяет представления children, поэтому этот метод ничего не будет делать с контейнерами, так как они находятся в корне.

Я решил, что поместил два контейнера в UIStackView в Interface Builder и сделал свойство этого стека в коде, а затем обновил ось в зависимости от ориентации. Например, в Objective-C:

  @property (слабый, неатомный) IBOutlet UIStackView * rootStack;

//...

- (UITraitCollection *) overrideTraitCollectionForChildViewController: (UIViewController *) childViewController
{   if (UI_USER_INTERFACE_IDIOM()!= UIUserInterfaceIdiomPad) {       return [super overrideTraitCollectionForChildViewController: childViewController];   }
   if (CGRectGetWidth (self.view.bounds) < CGRectGetHeight (self.view.bounds)) {       self.rootStack.axis = UILayoutConstraintAxisVertical;       return [UITraitCollection traitCollectionWithHorizontalSizeClass: UIUserInterfaceSizeClassCompact];   }   else {       self.rootStack.axis = UILayoutConstraintAxisHorizontal;       return [UITraitCollection traitCollectionWithHorizontalSizeClass: UIUserInterfaceSizeClassRegular];
}
Код>

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

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

Ответ 3

Я клонировал ваш код из репозитория: https://github.com/MaikoHermans/sizeClasses.git И редактируемый код помещает приведенный ниже код в ваш контроллер, он будет работать нормально и не повлияет на ваш дизайн в iPads.   import UIKit

class RootViewController: UIViewController {

   override func viewDidLoad() {
      super.viewDidLoad()
      // Do any additional setup after loading the view.
   }

   override func overrideTraitCollectionForChildViewController(childViewController: UIViewController) -> UITraitCollection? {
      if view.bounds.width < view.bounds.height {
         return UITraitCollection(horizontalSizeClass: .Unspecified)
      } else {
         return UITraitCollection(horizontalSizeClass: .Regular)
      }
   }
}

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