Swift:根据设备方向更改 view/screen。 "efficiency wise" 更好的选择是什么?
Swift: Changing view/screen depending on device orientation. What is "efficiency wise" the better option?
简介
我正在创建一个日历应用程序,其中一个屏幕有横向视图和纵向视图。为简单起见,在 iOS 苹果日历中,横向视图是周视图(即与纵向视图完全不同)。
问题
我感觉当前代码中的代码结构很糟糕并且可能会降低效率。因为我基本上同时使用用户电池和 CPU 进行周视图和纵向视图,即使不是每个人都使用周视图。 根据设备旋转实现不同演示的更好做法是什么?
问题
- 哪种模式更有效?有没有我没有考虑过的第三个选项会带来更好的性能?
我的尝试
(我还包含了一个代码示例(下方),展示了我在代码中对这些尝试的实现。)
两个 UIViewController
根据 viewWillTransition()
中的设备方向条件被连续和“弹出”。尽管由于该方法在当前 memory/navigationStack 中的所有视图控制器中触发,这很快就失去了控制,如果您在右横向和左横向之间切换,则会导致导航堆栈中出现额外的 viewControllers 副本。
使用一个 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(例如其他具有横向模式的视图控制器)。为不同的布局模式设置两个视图并不 易于维护,但如果这是显示模式之间差异的唯一方法,那确实是一个很好的解决方案。而且它比具有非常相似逻辑的两个视图控制器更容易维护。
简介
我正在创建一个日历应用程序,其中一个屏幕有横向视图和纵向视图。为简单起见,在 iOS 苹果日历中,横向视图是周视图(即与纵向视图完全不同)。
问题
我感觉当前代码中的代码结构很糟糕并且可能会降低效率。因为我基本上同时使用用户电池和 CPU 进行周视图和纵向视图,即使不是每个人都使用周视图。 根据设备旋转实现不同演示的更好做法是什么?
问题
- 哪种模式更有效?有没有我没有考虑过的第三个选项会带来更好的性能?
我的尝试
(我还包含了一个代码示例(下方),展示了我在代码中对这些尝试的实现。)
两个
UIViewController
根据viewWillTransition()
中的设备方向条件被连续和“弹出”。尽管由于该方法在当前 memory/navigationStack 中的所有视图控制器中触发,这很快就失去了控制,如果您在右横向和左横向之间切换,则会导致导航堆栈中出现额外的 viewControllers 副本。使用一个
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(例如其他具有横向模式的视图控制器)。为不同的布局模式设置两个视图并不 易于维护,但如果这是显示模式之间差异的唯一方法,那确实是一个很好的解决方案。而且它比具有非常相似逻辑的两个视图控制器更容易维护。