Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Safe Area changes in parent VC when presenting modally VC in landscape

Safe Area Insets in first UIViewController changes to Safe Area Inset for landscape when I present SecondViewController, which supports only landscape orientation.

GIF with described bug

GIF with described bug that touches TabBar and TableView

FirstViewController:

class ViewController: UIViewController {

  @IBAction func showSecondVC(_ sender: Any) {
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let controller = storyboard.instantiateViewController(withIdentifier: "SecondViewController")

    self.present(controller, animated: true, completion: {
      print("completed")
    })
  }

  override func viewSafeAreaInsetsDidChange() {
    print(view.safeAreaInsets)
    super.viewSafeAreaInsetsDidChange()
    print(view.safeAreaInsets)
  }
}

Second ViewController:

class SecondViewController: UIViewController {
  override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
    return [.landscape]
  }

  @IBAction func dismissYourSelff(_ sender: Any) {
    self.dismiss(animated: true, completion: nil)
  }
}

Console output:

UIEdgeInsets(top: 44.0, left: 0.0, bottom: 34.0, right: 0.0)
UIEdgeInsets(top: 44.0, left: 0.0, bottom: 34.0, right: 0.0)
UIEdgeInsets(top: 0.0, left: 44.0, bottom: 21.0, right: 44.0)
UIEdgeInsets(top: 0.0, left: 44.0, bottom: 21.0, right: 44.0)
completed
like image 379
filletofish Avatar asked Nov 10 '17 13:11

filletofish


1 Answers

That's how I solved the problem with constraints: https://gist.github.com/filletofish/b56600e9e661aa6e49cc0a56a98b37a3

I had to use snapshots to prevent wrong layout of TabBar and TableView.

override func present(_ viewControllerToPresent: UIViewController, animated flag: Bool, completion: (() -> Void)? = nil) {
    var completionToRemoveSnapshot: (() -> ())? = nil

    let shouldUseSnapshot = SDiOSVersion.deviceSize() == .Screen5Dot8inch &&
      viewControllerToPresent.supportedInterfaceOrientations == .landscape

    if shouldUseSnapshot {
      if let snapShot = self.view.snapshotView(afterScreenUpdates: true) {
        viewController.view.addSubview(snapShot)
        completionToRemoveSnapshot = { snapShot.removeFromSuperview() }
      }
    }

    super.present(viewControllerToPresent, animated: flag, completion: {
      completionToRemoveSnapshot?()
      completion?()
    })
  }
like image 126
filletofish Avatar answered Sep 18 '22 15:09

filletofish