Введение
Я создаю приложение календаря, в котором один из экранов имеет альбомную и книжную ориентацию. Для простоты изобразите яблочный календарь iOS, в котором альбомный вид представляет собой недельный вид (то есть полностью отличается от портретного).
Выпуск
У меня появляется ощущение плохой структуры кода и потенциальной потери эффективности в моем текущем коде. Так как я в основном использую батарею пользователя и процессор для просмотра недели одновременно с портретным представлением, хотя не все используют представление недели. Каков наилучший способ реализации различных презентаций в зависимости от ротации устройства?
Вопрос
- Какой шаблон будет более эффективным подходом? Есть ли третий вариант, который я не учел и который улучшил бы производительность?
Мои попытки
(Я также включил пример кода (ниже), который показывает мою реализацию этих попыток в коде.)
Два UIViewController
с, которые выделяются и «выталкиваются» в зависимости от условий ориентации устройства в viewWillTransition()
. Хотя это быстро вышло из-под контроля, поскольку метод запускается во всех контроллерах представления, находящихся в данный момент в memory / navigationStack, что приводит к дополнительным копиям viewControllers в стеке навигации, если вы переключаетесь между правым и левым пейзажем.
Использование одного 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
}
}
}
Спасибо, что прочитали мой вопрос.