Задача компоновки - знать, сколько места вам нужно для игры.

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

Добавьте к своим неприятностям введение многозадачности в iOS, и перед нами станет невыполнимая миссия. К счастью, Apple не упустила этот момент, пытаясь его решить. С видео конкретно об их решении задачи в 2016 году, а именно о чертах здесь. Тема, я подозреваю, что все все еще борются с большим количеством упоминаний, совсем недавно, на WWDC 2019, это видео, 27 минут после презентации.

Документация по проблеме действительно резюмирует, посмотрите, прокрутите вниз, вниз и еще немного вниз.



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

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

Но хорошо, да, я вас слышу - решение простое. У вас geometryReader в SwiftUI, нет. Если по вертикали больше, чем по горизонтали, то вы в портретной ориентации, в противном случае вы должны быть в альбомной ориентации. Я тоже так подумал и написал эту маленькую хитрость.

Хак, который работает, но - только на iPhone [снова]. И - что еще хуже, geometryReader, похоже, вообще не поддерживает многооконность, даже не осознавая, что вы их запускаете. Это ошибка в считывателе геометрии - может быть.

Хорошо, почему мы такие глупые, что решение Apple не работает. Мы можем получить доступ к классам признаков, поскольку они известны, через переменную SwiftUI @Environment. Здесь показана очень простая реализация.

Но нет, остановитесь, вы же не хотите проверять и то, и другое одновременно. Этот код не будет работать как есть. Вам нужно действовать по одному или другому, но не по обоим. Чтобы исправить это, я добавил блокировку.

@State var lock = false
if !lock {
  lock = true
  print("hz \(horizontalSizeClass) vt \(verticalSizeClass)")
  DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
    lock = false
  }
}

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

Все это подводит меня к концу этой короткой, но, надеюсь, полезной статьи по этой теме. Следуйте за мной на medium.com, чтобы увидеть больше статей. Я опубликовал почти 100 в 2019 году и надеюсь сделать еще больше в 2020 году.



Сохраняйте спокойствие, продолжайте кодировать.