迅速:根据设备方向更改视图/屏幕。什么是“效率明智”的更好选择?

时间:2018-11-09 15:08:25

标签: ios swift orientation landscape-portrait device-orientation

简介

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

问题

在我当前的代码中,我感觉到代码结构不好,效率可能降低。因为我基本上将用户电池和CPU与纵向视图同时用于周视图,即使不是每个人都使用周视图。 根据设备旋转情况实施不同的演示的更好的做法是什么?

问题

  • 哪种模式更有效?我没有想到的第三种选择会导致更好的性能吗?

我的尝试

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

  1. 根据UIViewController中设备方向的情况,会隔离并“弹出”两个viewWillTransition()。尽管由于该方法在内存/ navigationStack中当前触发的所有视图控制器中触发而很快变得不合时宜,但如果您在右横向和左横向之间进行交换,则会导致导航堆栈中有更多viewControllers副本。

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

代码示例

(我提供了两种简化来说明我的上述尝试,下面的示例中未包括诸如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 :(得分:0)

我肯定会选择选项 2号

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