Изменение адаптивности Popover в iOS 8.3
История написания этой статьи связана с изучением работы 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 в ландшафтном режиме как FormSheets, то есть модально. Это совершенно неожиданно и неудобно. Воспользовавшись новым 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».