Swift: изменение вида / экрана в зависимости от ориентации устройства. Что такое «мудрый по эффективности» лучший вариант? - PullRequest
0 голосов
/ 09 ноября 2018

Введение

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

Выпуск

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

Вопрос

  • Какой шаблон будет более эффективным подходом? Есть ли третий вариант, который я не учел и который улучшил бы производительность?

Мои попытки

(Я также включил пример кода (ниже), который показывает мою реализацию этих попыток в коде.)

  1. Два UIViewController с, которые выделяются и «выталкиваются» в зависимости от условий ориентации устройства в viewWillTransition(). Хотя это быстро вышло из-под контроля, поскольку метод запускается во всех контроллерах представления, находящихся в данный момент в memory / navigationStack, что приводит к дополнительным копиям viewControllers в стеке навигации, если вы переключаетесь между правым и левым пейзажем.

  2. Использование одного UIViewController и двух UIView подклассов, которые инициализируются и обмениваются данными с контроллером представления через шаблон протокола делегата. В котором во время viewWillTransition() я просто анимирую альфа-изменение между двумя UIViews в зависимости от ориентации устройства.

Пример кода

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

Попытка 1:

class PortraitCalendar: UIViewController {
    let portraitCalendarView : MonthCalendar = {
        // Setup of my portrait calendar, it is a UICollectionView subclass.
    }

     override func viewDidLoad() {
         super.viewDidLoad()
         view.addSubview(portraitCalendarView)
         // Additional setup..
     }

     override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
         super.viewWillTransition(to: size, with: coordinator)
         if UIDevice.current.orientation.isLandscape {
              performSegue(withIdentifier: "toLandscapeCalendar", sender: nil)
         } 
     }
 }

 class LandscapeCalendar: UIViewController {
     let landscapeView : LandscapeView = {
          // Setup of the landscape view, a UICollectionView subclass.
     }
     override func viewDidLoad() {
         super.viewDidLoad()
         view.addSubview(landscapeView)
         // Additional setup..
     }

     override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
         super.viewWillTransition(to: size, with: coordinator)
         if UIDevice.current.orientation.isPortrait {
              navigationController?.popViewController(animated: true)
         } 
     }
 }

Попытка 2:

class PortraitCalendar: UIViewController, LandscapeCalendarDelegate {
    let portraitCalendarView : MonthCalendar = {
        // Setup of my portrait calendar, it is a UICollectionView subclass.
    }

    // UIView subclass with a UICollectionView within it as a week calendar.
    let landscapeCalendar = LandscapeView() 

    override func viewDidLoad() {
        super.viewDidLoad()
        view.addSubview(portraitCalendarView)
        view.addSubview(landscapeCalendar)
        landscapeCalendar.alpha = 0
        portraitCalendarView.alpha = 1
        // Constraints and additional setup as well of course.
    }

    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransition(to: size, with: coordinator)
        if UIDevice.current.orientation.isLandscape {
            navigationController?.isToolbarHidden = true
            self.view.layoutIfNeeded()

            landscapeCalendarDelegate?.splitCalendarViewWillAppear()
            UIView.animate(withDuration: 0.1) {
                self.portraitCalendarView.alpha = 0
                self.landscapeCalendar.alpha = 1
            }
        } else {
            self.portraitCalendarView.alpha = 1
            self.landscapeCalendar.alpha = 0
        }
     }
}

Спасибо, что прочитали мой вопрос.

1 Ответ

0 голосов
/ 09 ноября 2018

Я бы определенно выбрал вариант номер 2 .

Таким образом вы инкапсулируете всю логику , связанную с календарем, например, для добавления события или его отображения, в одном контроллере представления, без необходимости переопределения логической логики в другом месте (например, в другом контроллере представления). с ландшафтным режимом). Наличие двух видов для разных режимов компоновки не просто в ТО , но если это единственный способ показать разницу между режимами, это действительно хорошее решение. И это намного проще в обслуживании, чем два контроллера представления с очень похожей логикой.

...