Swift viewWillTransition не вызывается
Я создаю полноэкранную галерею изображений, используя 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
вызывается также внутри функции. Может кто-нибудь помочь мне в том, что может быть причиной этой проблемы?
6 ответов
Если вы просто беспокоитесь о макете, когда устройство вращается, пожалуйста, используйте:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
collectionView.collectionViewLayout.invalidateLayout()
collectionView.layoutIfNeeded()
}
Из яблочных документов:
public func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)
Этот метод вызывается, когда размер представления контроллера представления изменяется его родителем (то есть для корневого контроллера представления, когда его окно поворачивается или изменяется). Если вы переопределите этот метод, вам следует либо вызвать 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)
}
func deviceOrientationDidChange(_ notification: Notification) {
let orientation = UIDevice.current.orientation
print(orientation)
}
Я хотел бы опубликовать ответ, который я оставил в другой теме, описывающей ту же проблему.
Люди уже объяснили, что надо звонить супер. Я хотел бы добавить информацию, которая может помочь людям, которые столкнулись бы с тем, с чем я столкнулся.
Сценарий: Parent -> Child (viewWillTransition не вызывается в child)
Если ваш контроллер представления является дочерним контроллером представления, то проверьте, вызывается ли родительский контроллер представления, и вызывается ли там 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
}
}
PS - Это случилось со мной, потому что я не написал код для родителя.
Я заменил
func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)
по
func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator)
и у меня это работает.
Если ваш ViewController является дочерним ViewController, и вы добавили его представление в представление родительского ViewController
В родительском ViewController, где вы добавили
self.view.addSubview(childViewController.view)
Также добавьте
self.addChild(childViewController)
Вот как я это исправил:
Перейти к цели проекта - Общие сведения - Информация о развертывании
Tick Device Orientations, которые поддерживает приложение
Также вам нужно (изменить UIInterfaceOrientationMask.all
за что уместно)
override var supportedInterfaceOrientations : UIInterfaceOrientationMask {
get {
return UIInterfaceOrientationMask.all;
}
}
для ViewController.
Может вам нужно установить
Supported interface orientations
в
Info.plist
:
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>