Yuuu
Yuuu

Reputation: 879

ViewWillAppear is not called when the top-front VC is dismissed

as I wrote in the title, I'm not sure why ViewWillAppear is not called when another VC is dismissed. I think my project is a little bit tricky, so I'm gonna explain what is going on in my project.

enter image description here

Mostly, I configure UIs in code. I have two VCs, ListVC and CameraVC, and I have a tab bar and a navigation var in ListVC, which I configured all in code. So in the SceneDelegate I wrote something like

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    guard let scene = (scene as? UIWindowScene) else { return }
    window = UIWindow(frame: scene.coordinateSpace.bounds)
    window?.windowScene = scene
    window?.rootViewController = createTabBar()
    window?.makeKeyAndVisible()
}

func createTabBar() -> CustomTabBarController {
    let tabbar = CustomTabBarController()
    tabbar.viewControllers = tabbar.setUpTabbarItems()
    return tabbar
}

and in the CustomTabBarController class, since I just wanted to present the event list, I added

func createListNC() -> UINavigationController {
    let ListVC = ListViewController()
    ListVC.tabBarItem = UITabBarItem(title: "", image: UIImage(named: "add-icon"), tag: 0)
    return UINavigationController(rootViewController: ListVC)
}


func setUpTabbarItems() -> [UIViewController]{
    return [createListNC()]
}

So now I can display List VC on the home of the app. However, I made the CameraVC all in the storyboard and I added the following code when a user taps one of the Event cells in List VC and it presents CamearaVC.

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    let storyboard = UIStoryboard(name: "Camera", bundle: nil)
    let CameraVC = storyboard.instantiateViewController(identifier: "Camera")
    self.present(CameraVC, animated: true, completion: nil)
}

So I can also present the CameraVC from ListVC.

But the problem happens when I want to back from CameraVC to ListVC. I added IBAction to the button saying "< back" in CameraVC, and I can dismiss the CameraVC, however, since the cameraVC's screen is horizontal, the ListVC also stack with horizontal, which I want to make the ListVC vertical.

@IBAction func unwindToLiveList (_ segue: UIStoryboardSegue) {
    self.presentingViewController?.dismiss(animated: true, completion: nil)
}

So, I was planning to write a code for fixing the orientation of the app when a user back from CameraVC to ListVC.

I just wanted to know where I should put that fixing orientation code, so I added viewwillappear and some print statements to ListVC, but none of them are called when back from CameraVC to ListVC. I also wrote the same code in CustomTabBarController class, but it is never called...

So, I was wondering where and which file I can write the code for fixing the orientation to trigger when the user came back from CameraVC to ListVC. Also, if anyone can explain why this is happening, please let me know.

Upvotes: 2

Views: 1828

Answers (2)

Andrea
Andrea

Reputation: 26383

The reason is about the change they had made in iOS13 (or 14). Before the default modal presentation mode (it seems that you are presenting modally) was full screen, now they are presented over the current context without making the presenting view controller to disappear, that is why willAppear is not called, it' already there.
If you want to change that behavior you can setup a different presentation style as .fullScreen.

Upvotes: 0

SeaSpell
SeaSpell

Reputation: 758

The problem seems to be the way View controllers are presented now. Since the bottom view controller never actually leaves view will appear isn't called when dismissing anymore. I'm pretty sure it did in the past, but now that controllers present as overlays I guess it doesn't anymore.

However, you are in a navigation stack so if you just use that you'll get a free back button and viewWillAppear will get called.

    let cameraVC = storyboard.instantiateViewController(identifier: "Camera")
    self.navigationController?.pushViewController(cameraVC, animated: true)

As I said you'll get a free back button on cameraVC and that will pop cameraVC off the stack for you.

If you want to keep from using the navigationController for some reason take a look at

https://developer.apple.com/documentation/uikit/uicontentcontainer/1621466-viewwilltransition

   override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        print(size)
   }

Upvotes: 1

Related Questions