История написания этой статьи связана с изучением работы Popover в iOS 8 по материалам курса лекций стэнфордского университете «Разработка iOS 8 приложений на Swift. CS193P 2015 г.» В Лекции 7 профессор разбирает, как создать Popover в виде маленького «всплывающего» окошка как на iPad (что получается по умолчанию), так и на iPhone ( в методе делегата нужно сказать «НЕТ» адаптации).


Но в iOS 8.3 все нарушается:
  • на iPhone Popover окошки появляются ввиде модального окна на весь экран, с которого не знаешь как уйти,
  • а на iPhone 6 Plus в ландшафтном режиме (который должен работать как на iPad по умолчанию) вообще окно отображается модально как FormSheet, и с него также невозможно никуда уйти.




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




Адаптивность Popover до iOS 8.3



Само по себе Popover — не UIViewController. Он появляется на экране, используя так называемый механизм Presentation Controller. Popover на iPad “всплывает” так, как вы видели на рисунке выше для iOS 8.2. В виде маленького окошка со стрелкой. На iPhone Popover адаптируется и превращается вместо маленького окошка в модальное окно на полный экран. Оно не “всплывает” как что-то маленькое на iPhone. Что касается iPhone 6 Plus, то в портретном режиме он ведет себя как iPhone ( модальное окно на весь экран), а в ландшафтном режиме как iPad ( маленькое «всплывающее» окно). Такая Адаптация делается автоматически. iOS 8 автоматически делает эту адаптацию также, как автоматически адаптируется Split View и Navigation Controller для iPhone.
Перед iOS 8.3, Адаптивность Popover работала, когда горизонтальный size class изменяется от Regular к Compact.

Это означает, что система iOS 8 определяет Any-Compact не как обычную среду для Popover, а как нуждающуюся в адаптивном стиле презентации. Но используя делегата UIPopoverPresentationControllerDelegate, вы можете воздействовать на эту адаптацию и даже запретить ее, чтобы на любом приборе Popover работала как на iPad.

Для этого у делегата UIPopoverPresentationControllerDelegate есть метод

   func adaptivePresentationStyleForPresentationController(controller: UIPresentationController) -> UIModalPresentationStyle 


, который позволяет изменить адаптивный стиль презентации. Более точно, он возвращается стиль презентации, используемый для случая, когда представляемый View Controller становится горизонтально Compact.
Нам достаточно использовать этот метод таким образом

   func adaptivePresentationStyleForPresentationController(controller: UIPresentationController) -> UIModalPresentationStyle {
        return UIModalPresentationStyle.None
}


чтобы на любом приборе Popover работала как на iPad.
Но в в iOS 8.3 это не работает — результат вы видите на рисунке сверху.

Новое в iOS 8.3



iOS 8.3 «думает» об Адаптации немного иначе, и это нужно принимать во внимание. Адаптивность больше не фокусируется исключительно на HorizontalSize в iOS 8.3. Для этого public API делегата UIAdaptivePresentationControllerDelegate (это superclass для UIPopoverPresentationControllerDelegate ) усилился новым методом:

func adaptivePresentationStyleForPresentationController(controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle


Заметьте, что у нового метода появился дополнительный аргумент типа UITraitCollection. Теперь это означает, что мы можем решать, какие комбинации size class заслуживают адаптивного стиля.

«Засада» в iOS 8.3 Popover



Пример Popover выше был выбран неслучайно. Если вы создадите приложение в iOS 8.3 SDK с Popover, то заметите, что Popovers теперь отображается на iPhone 6 Plus в ландшафтном режиме как FormSheet, то есть модально. Это совершенно неожиданно и неудобно. Воспользовавшись новым API, оказалось возможным вернуть приложение к правильному функционированию. Но также удалось обнаружить, что по умолчанию, UIPopoverPresentationController теперь выбирает адаптивный стиль .FormSheet для Regular-Compact среды. Хорошо, что у нас появился новый public API для этих новых вариантов адаптации, и мы можем его очень просто использовать

// Для iOS 8.3 SDK
    
    func adaptivePresentationStyleForPresentationController(controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
        return UIModalPresentationStyle.None
    }


Мне все-таки кажется, что это странное изменение.

Возможное будущее Адаптивности



С этим новым API, Адаптивность больше не означает горизонтального Сompact. Я думаю, что новое определение Адаптивности Apple _not Regular– по обоим осям. Если один из size classes не являетсяi Regular, презентация нуждается в адаптации. В настоящий момент у нас два size classes — Compact и Regular — но Apple в будущем может ввести еще больше size classes ( возможно, iPad Pro или Apple TV). Теперь мы можем думать о Any-Compact или Compact-Any как об адаптивных размерах, но мы должны настраиваться на Any-!Regular и !Regular-Any. Возможно, что в будущем будут приниматься во внимание не только малые TraitСollections, но и большие.

Материал основан на статье «Adaptability Changes in iOS 8.3».

Комментарии (9)


  1. cher11
    14.04.2015 17:03

    Качество перевода очень далеко от идеального, чего стоит «Возможное будущее Адаптивность».
    Да и скриншот, если честно, ни разу не очевидный — зачем было их так лепить друг на друга?
    Ну а по теме — Apple, конечно, очень «радуют» подобными «усовершенствованиями», от которых одинаковый код ведет себя по-разному.


    1. WildGreyPlus Автор
      14.04.2015 17:29
      -1

      К сожалению, Вы основного не поняли, код-то как раз разный.


      1. cher11
        14.04.2015 17:56

        То есть в статье говорится не о том, что один и тот же код, будучи запущенным на iOS 8.2, отобразит правильный Popover, а на 8.3 отобразится нечто без стрелки, растянутое по экрану?


        1. WildGreyPlus Автор
          14.04.2015 18:15
          -1

          Нет, не об этом. Popover на iOS 8.2 в силу новой концепции «адаптивности» работает так, что на всех iPhone (кроме iPhone 6 Plus в ландшафтном режиме) будет представлять Popover как модальное окно на весь экран. Это если ничего не предпринимать. Popover на iOS 8.3 в силу концепции «адаптивности» все также будет работать плохо на iPhone, даже еще хуже, так как такое же модальное окно (правда не на весь экран) теперь будет и у iPhone 6 Plus в ландшафтном режиме. Если тоже ничего не предпринимать.Бороться с этим, если вы хотите на любом приборе «настоящий» Popover как на iPad, нужно по-разному, так как сама концепция «адаптивность» поменялась. Смысл статьи в том, что поменялась концепция «адаптивность» ( теперь она не нацелена на горизонтальный Compact) — поменялся метод. Вот и все, но это нужно знать, собственно об этом и статья. Пытались понять, почему поменялась концепция, возможно, это связано с выходом новых приборов.


  1. IgorRastvorov
    14.04.2015 21:42

    Идентификаторы через чур длинные, очень неприятно читать.


    1. WildGreyPlus Автор
      14.04.2015 22:19
      -2

      Слово «чересчур» пишется в одно слово и через «с».


      1. IgorRastvorov
        15.04.2015 22:47

        Может стоило мне в личку написать по этому поводу? Вам так не кажется, уважаемый?


  1. egormerkushev
    20.04.2015 16:30

    Спасибо! Ваш перевод помог разобраться!


    1. WildGreyPlus Автор
      20.04.2015 21:02

      Приятно быть полезным. Хотя проблема невелика, но, как говорится, «дьявол — в деталях».