Swift 未调用 viewWillTransition
Swift viewWillTransition not called
我正在使用 UICollectionView
创建全屏图片库。当用户旋转设备时,我对
内的 UICollectionView
执行更新
func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)
我以模态方式显示此 UIViewController
并且 UICollectionView
占据了整个屏幕。在 viewDidLoad
内,我将流布局创建为:
let flowLayout = UICollectionViewFlowLayout()
flowLayout.scrollDirection = .horizontal
flowLayout.minimumInteritemSpacing = 0
flowLayout.minimumLineSpacing = 0
photosCollectionView.isPagingEnabled = true
photosCollectionView.setCollectionViewLayout(flowLayout, animated: true)
我也有尺码:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return photosCollectionView.frame.size
}
当我旋转我的设备时,viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)
永远不会被调用,这会导致 UICollectionViewLayout
不更新。当我旋转设备时,我确实收到消息:
The behavior of the UICollectionViewFlowLayout is not defined because: the item height must be less than the height of the UICollectionView minus the section insets top and bottom values, minus the content insets top and bottom values.
我在网上看到可以补充:
self.automaticallyAdjustsScrollViewInsets = false
到 UIViewController
,但这没有影响。 UICollectionView
没有内容或部分插入。
我也在函数中调用了 super.viewWillTransition
。任何人都可以帮助我解决可能导致此问题的原因吗?
如果您只是关心设备旋转时的布局,请使用:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
collectionView.collectionViewLayout.invalidateLayout()
collectionView.layoutIfNeeded()
}
来自苹果文档:
public func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)
This method is called when the view controller's view's size is
changed by its parent (i.e. for the root view controller when its
window rotates or is resized).
If you override this method, you should either call super to propagate the change to children or manually forward the change to
children.
我想您可能会在该视图的父视图上调用此函数而不调用 super
解决方法还包括注册设备轮换:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
NotificationCenter.default.addObserver(self, selector: #selector(deviceOrientationDidChange), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
NotificationCenter.default.removeObserver(self)
}
@objc func deviceOrientationDidChange(_ notification: Notification) {
let orientation = UIDevice.current.orientation
print(orientation)
}
我就是这样解决的:
转到项目目标 - 常规 - 部署信息
勾选应用程序支持的设备方向
您还需要(根据需要更改 UIInterfaceOrientationMask.all
):
override var supportedInterfaceOrientations : UIInterfaceOrientationMask {
get {
return UIInterfaceOrientationMask.all;
}
}
对于 ViewController。
我想重新发布我在描述相同问题的另一个 thread 中留下的答案。
人们已经解释过你必须调用super。我想添加一条信息,可能会帮助那些会遇到我所面临的情况的人。
场景:父级 -> 子级(未在子级中调用 viewWillTransition)
如果您的视图控制器是 child 视图控制器,则检查是否调用了 parent 视图控制器委托以及是否调用了 super那里。 否则不会传播到子视图控制器!
class ParentViewController: UIViewController {
func presentChild() {
let child = ChildViewController()
present(child, animated: false, compeltion: nil)
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator) // If this line is missing your child will not get the delegate call in it's viewWillTransition
// Do something
}
}
class ChildViewController: UIViewController {
// This method will not get called if presented from parent view controller and super is not called inside the viewViewWillTransition available there.
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
//Do something
}
}
P.S - 这件事发生在我身上,因为父级的代码是别人写的,他们忘了调用 super。
我换了
func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)
来自
func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator)
它对我有用。
如果您的 ViewController
是 child ViewController
并且您已将它的视图添加到 parent ViewController
的视图中,请执行以下操作:
在 parent ViewController
您添加的地方
self.view.addSubview(childViewController.view)
同时添加
self.addChild(childViewController)
也许您需要在 Info.plist
中设置 Supported interface orientations
:
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
我正在使用 UICollectionView
创建全屏图片库。当用户旋转设备时,我对
UICollectionView
执行更新
func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)
我以模态方式显示此 UIViewController
并且 UICollectionView
占据了整个屏幕。在 viewDidLoad
内,我将流布局创建为:
let flowLayout = UICollectionViewFlowLayout()
flowLayout.scrollDirection = .horizontal
flowLayout.minimumInteritemSpacing = 0
flowLayout.minimumLineSpacing = 0
photosCollectionView.isPagingEnabled = true
photosCollectionView.setCollectionViewLayout(flowLayout, animated: true)
我也有尺码:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return photosCollectionView.frame.size
}
当我旋转我的设备时,viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)
永远不会被调用,这会导致 UICollectionViewLayout
不更新。当我旋转设备时,我确实收到消息:
The behavior of the UICollectionViewFlowLayout is not defined because: the item height must be less than the height of the UICollectionView minus the section insets top and bottom values, minus the content insets top and bottom values.
我在网上看到可以补充:
self.automaticallyAdjustsScrollViewInsets = false
到 UIViewController
,但这没有影响。 UICollectionView
没有内容或部分插入。
我也在函数中调用了 super.viewWillTransition
。任何人都可以帮助我解决可能导致此问题的原因吗?
如果您只是关心设备旋转时的布局,请使用:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
collectionView.collectionViewLayout.invalidateLayout()
collectionView.layoutIfNeeded()
}
来自苹果文档:
public func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)
This method is called when the view controller's view's size is changed by its parent (i.e. for the root view controller when its window rotates or is resized). If you override this method, you should either call super to propagate the change to children or manually forward the change to children.
我想您可能会在该视图的父视图上调用此函数而不调用 super
解决方法还包括注册设备轮换:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
NotificationCenter.default.addObserver(self, selector: #selector(deviceOrientationDidChange), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
NotificationCenter.default.removeObserver(self)
}
@objc func deviceOrientationDidChange(_ notification: Notification) {
let orientation = UIDevice.current.orientation
print(orientation)
}
我就是这样解决的:
转到项目目标 - 常规 - 部署信息
勾选应用程序支持的设备方向
您还需要(根据需要更改 UIInterfaceOrientationMask.all
):
override var supportedInterfaceOrientations : UIInterfaceOrientationMask {
get {
return UIInterfaceOrientationMask.all;
}
}
对于 ViewController。
我想重新发布我在描述相同问题的另一个 thread 中留下的答案。
人们已经解释过你必须调用super。我想添加一条信息,可能会帮助那些会遇到我所面临的情况的人。
场景:父级 -> 子级(未在子级中调用 viewWillTransition)
如果您的视图控制器是 child 视图控制器,则检查是否调用了 parent 视图控制器委托以及是否调用了 super那里。 否则不会传播到子视图控制器!
class ParentViewController: UIViewController {
func presentChild() {
let child = ChildViewController()
present(child, animated: false, compeltion: nil)
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator) // If this line is missing your child will not get the delegate call in it's viewWillTransition
// Do something
}
}
class ChildViewController: UIViewController {
// This method will not get called if presented from parent view controller and super is not called inside the viewViewWillTransition available there.
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
//Do something
}
}
P.S - 这件事发生在我身上,因为父级的代码是别人写的,他们忘了调用 super。
我换了
func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)
来自
func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator)
它对我有用。
如果您的 ViewController
是 child ViewController
并且您已将它的视图添加到 parent ViewController
的视图中,请执行以下操作:
在 parent ViewController
您添加的地方
self.view.addSubview(childViewController.view)
同时添加
self.addChild(childViewController)
也许您需要在 Info.plist
中设置 Supported interface orientations
:
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>