web-dev-qa-db-ja.com

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
Mike Walker

デバイスが回転するときのレイアウトだけが気になる場合は、次を使用してください。

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    collectionView.collectionViewLayout.invalidateLayout()
    collectionView.layoutIfNeeded()
}

Apple docs:

public func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)

このメソッドは、View Controllerのビューのサイズがその親によって変更されたときに呼び出されます(つまり、ウィンドウが回転またはサイズ変更されたときのルートView Controllerの場合)。このメソッドをオーバーライドする場合は、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)
}
13
zombie

同じ問題を説明している別の スレッド に残した回答を再投稿したいと思います。


superを呼び出さなければならないことはすでに説明されています。私が直面したことに直面したであろう人々を助けるかもしれない情報を追加したいと思います。

シナリオ:親->子(viewWillTransitionは子で呼び出されません)


ビューコントローラがビューコントローラである場合は、ビューコントローラデリゲートが呼び出されているかどうか、およびsuperがそこで呼び出されます。そうしないと、子ViewControllerに伝播されません。

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
    }
}

追伸-私は親のコードを書かなかったので、これは私に起こりました。

5
Rakesha Shastri

これは私がそれを修正した方法です:

プロジェクトターゲット-一般-展開情報に移動します

アプリがサポートするデバイスの向きにチェックマークを付ける

また、必要です(change UIInterfaceOrientationMask.all適切なものは何でも):

override var supportedInterfaceOrientations : UIInterfaceOrientationMask {
    get {
        return UIInterfaceOrientationMask.all;
    }
}

viewControllerの場合。

0
cyanide

交換しました

func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)

沿って

func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator)

そしてそれは私のために働きます。

0
David Chea