iPad横屏分屏模式下viewWillTransition偶发不触发问题咨询
问题
在iPad上(已启用所有默认支持的屏幕方向),以FormSheet样式present UIViewController时出现异常:
- 竖屏模式下,旋转、切换分屏、调整分屏大小或切换至SlideOver操作均能正常触发
viewWillTransition(to:with:)方法; - 横屏模式下,分屏状态调整应用大小或切换至SlideOver时,该方法有时无法触发。
已在模拟器和真机上完成测试,演示代码如下:
ViewController 代码
class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. } override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) } @IBAction func button(_ sender: Any) { let vc = storyboard?.instantiateViewController(withIdentifier: "SecondViewController") as! SecondViewController if self.traitCollection.userInterfaceIdiom == .phone { vc.modalPresentationStyle = .fullScreen } else { vc.modalPresentationStyle = .formSheet } vc.modalTransitionStyle = .coverVertical self.present(vc, animated: true, completion: nil) } }
SecondViewController 代码
class SecondViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. } override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) DispatchQueue.main.async { print("Transition Detected") } } }
解决方案
viewWillTransition(to:with:)主要针对设备旋转这类明确的过渡场景,而横屏分屏调整、SlideOver切换时,FormSheet的尺寸变化可能未被系统判定为“过渡”操作,导致回调不触发。可以通过以下两种方法覆盖所有尺寸变化场景:
方法1:监听Trait Collection变化
重写traitCollectionDidChange(_:)方法,跟踪视图尺寸变化:
class SecondViewController: UIViewController { private var previousSize: CGSize? override func viewDidLoad() { super.viewDidLoad() previousSize = view.bounds.size } override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) let currentSize = view.bounds.size guard let previousSize = previousSize, currentSize != previousSize else { return } self.previousSize = currentSize print("Size changed detected: \(currentSize)") // 在此处理尺寸变化逻辑 } override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) DispatchQueue.main.async { print("Transition Detected") } previousSize = size } }
方法2:监听视图Bounds变化
通过重写viewDidLayoutSubviews()方法检测尺寸变化:
class SecondViewController: UIViewController { private var previousBounds: CGRect? override func viewDidLoad() { super.viewDidLoad() previousBounds = view.bounds } override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() let currentBounds = view.bounds guard let previousBounds = previousBounds, currentBounds != previousBounds else { return } self.previousBounds = currentBounds print("Bounds changed detected: \(currentBounds.size)") // 在此处理尺寸变化逻辑 } override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) DispatchQueue.main.async { print("Transition Detected") } } }
内容的提问来源于stack exchange,提问作者Mel
相关产品推荐
相关产品推荐

