Swift:根据设备方向更改 view/screen。 "efficiency wise" 更好的选择是什么?

Swift: Changing view/screen depending on device orientation. What is "efficiency wise" the better option?

简介

我正在创建一个日历应用程序,其中一个屏幕有横向视图和纵向视图。为简单起见,在 iOS 苹果日历中,横向视图是周视图(即与纵向视图完全不同)。

问题

我感觉当前代码中的代码结构很糟糕并且可能会降低效率。因为我基本上同时使用用户电池和 CPU 进行周视图和纵向视图,即使不是每个人都使用周视图。 根据设备旋转实现不同演示的更好做法是什么?

问题

我的尝试

(我还包含了一个代码示例(下方),展示了我在代码中对这些尝试的实现。)

  1. 两个 UIViewController 根据 viewWillTransition() 中的设备方向条件被连续和“弹出”。尽管由于该方法在当前 memory/navigationStack 中的所有视图控制器中触发,这很快就失去了控制,如果您在右横向和左横向之间切换,则会导致导航堆栈中出现额外的 viewControllers 副本。

  2. 使用一个 UIViewController 和两个 UIView 初始化的子类,并通过委托协议模式与视图控制器通信。在 viewWillTransition() 期间,我根据设备方向简单地设置了两个 UIViews 之间的 alpha 变化动画。

代码示例

(我已经提供了两个简化来说明我的上述尝试,下面的示例中不包括 UICollectionViews 的 dataSource 和委托方法等方法。)

尝试 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
        }
     }
}

感谢阅读我的问题。

我肯定会选择 数字 2

这样你就可以在一个视图控制器中封装所有与日历相关的逻辑,例如添加事件或显示它,而不需要在某个地方重新实现理智的逻辑else(例如其他具有横向模式的视图控制器)。为不同的布局模式设置两个视图并不 易于维护,但如果这是显示模式之间差异的唯一方法,那确实是一个很好的解决方案。而且它比具有非常相似逻辑的两个视图控制器更容易维护。