iOS Swift - Presenting View Controller sliding down while presenting new View Controller - ios

I present a View Controller in the following fashion:
let vc: ChangeDateViewController = storyboard!.instantiateViewControllerWithIdentifier("changedate") as! ChangeDateViewController
let navigationController = UINavigationController(rootViewController: vc) //ensures that the top navigation bar remains in the new View Controller
self.presentViewController(navigationController, animated: true, completion: nil)
For some reason, the base presenting View Controller slides down while the new View Controller is sliding up. Although the presenting works, it does look glitchy because the sliding down reveals the black background behind the views. Is this a common occurrence, and is there anything I can do to prevent it?

Try this:
let storyboard1 = UIStoryboard(name: "Main", bundle: nil)
let conn = storyboard1.instantiateViewControllerWithIdentifier("changedate") as! LMAddaccountMainVC
self.presentViewController(conn, animated: true, completion: nil)
This might be helpful to solve you issue.

Related

New iOS 13 Modal Presentation: Presenting Controller Doesn't Move Down

I have a weird behavior when presenting UIViewControllers modally in iOS 13. The new presentation style that I've seen all across iOS 13 looks like this:
The presenting view controller appears behind the presented view controller. It is also shifted down to mimic a "stack"
Meanwhile, when presenting view controllers through my app, I keep getting this effect:
The presenting view controller doesn't move at all when presenting a new view controller
I use this code to present this view controller:
let controller = storyboard?.instantiateViewController(withIdentifier: "tutorial") as! TutorialController
controller.modalPresentationStyle = .pageSheet
controller.modalTransitionStyle = .coverVertical
present(controller, animated: true, completion: nil)
Here is my question:
I'm wondering why this is happening and if there is a way to present view controllers in the normal iOS 13 style (with the presenting view controller moving back).
Thanks in advance!
Turns out the problem was my view controller hierarchy. I was able to fix it by making the presenting view controller the root view controller of my app. First I set the background controller as the root view controller by calling
window.rootViewController = self
and then using my previous code
let controller = storyboard?.instantiateViewController(withIdentifier: "tutorial") as! TutorialController
controller.modalPresentationStyle = .pageSheet
controller.modalTransitionStyle = .coverVertical
present(controller, animated: true, completion: nil)
I presented the view controller. Thanks to everyone who tried to help!
I think the issue can be resolved by using vc.modalPresentationStyle = .fullScreen if there is not UINavigationController , otherwise you can use these codes as follows:
let navigationController = UINavigationController(rootViewController: vc)
navigationController.modalPresentationStyle = .fullScreen
present(vc, animated: true)
because With iOS 13 this is a new feature that Apple has changed the default presentation style of View Controllers to a modal sheet from fullscreen in iOS 12
Programmatically:
let vc = UIViewController()
vc.modalPresentationStyle = .fullScreen //or .overFullScreen for transparency
self.present(vc, animated: true, completion: nil)
From storyboard:
That's it. No need to play with root controller or window at all.
For reference, visit this article.
iOS13: Let's say you have 3 view controllers: FirstVC, SecondVC, ThirdVC
FirstVC presents SecondVC with the below code:
let secondVC = SecondVC()
secondVC.modalPresentationStyle = .fullScreen
firstVC.present(secondVC, animated: true, completion: nil)
SecondVC presents ThirdVC with the below code:
let thirdVC = ThirdVC()
secondVC.present(thirdVC, animated: true, completion: nil)
Changing secondVC's modalPresentationStyle to .currentContext solves the problem.
We can change it in the Inspector Tool Bar. To Achieve it: head over to the fifth section of Inspector Tollbar then change the Presentation field to Full Screen.
This should be the only property you need to set
presentedViewController.modalPresentationStyle = .automatic
Detailed in
https://developer.apple.com/videos/play/wwdc2019/224/

How to present a popup view in full screen

I've following view configuration
Tab bar -> Nav controller -> View: Click on a button -> segue to-> Another view: Click on a button -> Popup view.
This modal view is on a different storyboard.
I want to present this model view in full screen. I've tried this solution mentioned on Presenting modal in iOS 13 fullscreen but it doesn't work. I've also tried few other solutions but the popup view is not showing over full screen, status bar is visible at the top.
How do I present modal view in a full screen?
let storyboard = UIStoryboard(name: "Other", bundle: Bundle.main)
guard let popupVC = storyboard.instantiateViewController(withIdentifier: "PopUpViewController") as? PopUpViewController else {
print("PopUpViewController not found")
return
}
popupVC.modalPresentationStyle = .fullScreen
self.present(popupVC, animated: true, completion: nil)
You could try presenting with the navigation controller.
let storyboard = UIStoryboard(name: "Other", bundle: Bundle.main)
guard let popupVC = storyboard.instantiateViewController(withIdentifier: "PopUpViewController") as? PopUpViewController else {
print("PopUpViewController not found")
return
}
var navigationController = UINavigationController(rootViewController: popupVC)
navigationController.modalPresentationStyle = .fullScreen
self.present(navigationViewController, animated: true, completion: nil)
An alternative would be to use presentViewController but presentViewController will only present one viewController modally over the currently visible viewController whereas presenting with the navigationController will give the flexibility to push further components on top, providing a smoother navigation experience with go back to previous page kind of behaviour.
Maybe try creating the view controller this way:
let popOverVC = UIStoryboard(name: "yourBoard", bundle: nil).instantiateViewController(withIdentifier: "YourViewController") as! YourViewController
self.addChild(popOverVC)
let lSs = UIScreen.main.bounds
popOverVC.view.frame = CGRect(x: 0, y: 0, width: lSs.width, height: lSs.height)
popOverVC.view.tag = tag
self.view.addSubview(popOverVC.view)
popOverVC.didMove(toParent: self)
Within the popup view controller class, add a method for animating its view in viewDidLoad.
Edit: I read your replies. The issue you are having is caused by not handling the status bar properly. Instead of trying to make this veiewcontroller fullscreen, simply hide the status bar
How do I hide the status bar in a Swift iOS app?
and bring it back when you want to see it again.

How to make the transition to a view controller with a navigation bar?

I have two modules that I need to connect.
The authorization module, which consists of 1 screen. There is no
controller Navigation on it and it is not in its stack.
Main application. The first screen is the root for the controller
navigation.
How can I implement the transition in case of successful authorization from the authorization screen to the main application in Swift code?
My screen scheme
SOLUTION:
I use this solution for my case:
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "rootVC")
UIApplication.shared.delegate?.window??.rootViewController = vc
view.present(vc, animated: true) {
self.view.dismiss(animated: false, completion: nil)
}
Give storyboardId "nav" to the Navigation Controller and then present it on your login view controller.
if let nav = self.storyboard?.instantiateViewController(withIdentifier: "nav") {
self.present(nav, animated: true, completion: nil)
}
on your navigation Controller on storyboard add your storyboard Id, for example I have named it as navController
In your code, from you want to show as the navigation controller as present, add this line
case if presented view Controller on same storyboard
if let navController = self.storyboard?.instantiateViewController(withIdentifier: "navController") {
self.present(navController, animated : true, completion : nil)
}
case if presented view controller on different storyboard
let storyboard = UIStoryboard(name : STORYBOARD_NAME, bundle : nil)
let nav = storyboard.instantiateViewController(withIdentifier: "navController")
self.present(navController, animated : true, completion : nil)

Swift How to present view in root navigation after dismiss modal

I'm trying to make ViewController present after Modal dismiss
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let chatRoomVC = storyboard.instantiateViewController(withIdentifier: "ChatRoomVCId") as! ChatRoomVC
chatRoomVC.hidesBottomBarWhenPushed = true
chatRoomVC.passValue = passValue
self.dismiss(animated: true, completion: {
self.present(chatRoomVC, animated: true, completion: nil)
})
But it will return "whose view is not in the window hierarchy!" maybe it's present a view after the controller dismissed
Notice the self in self.present, what you are doing, is basically tell the vc that you are dismissing to present a new vc, thats wrong way to do, the correct way is tell it's PARENT vc to present a new vc, by using delegate/unwind to call the parent vc to present new vc
You are using self. It means you are dismissing the current view controller. It should be the parent view controller who will present a new view controller.
When present from "Controller_A" to "Controller_B"-> present it like given below
--- View Controller A ---
self.navigationController?.present(Controller_B, animated: true, completion: nil)
When you want to dismiss "Controller_B" and present "Controller_C" using Navigation controller
--- View Controller B ---
let presenController : UINavigationController = self.presentingViewController as! UINavigationController
presentingController.dismiss(animated: true, completion: {
presenController.pushViewController(Controller_C, animated: true)
})

Replace rootViewController behind a modal view

With the following code I'm able to change the rootViewController behind a modal view :
let storyboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let signupVC = storyboard.instantiateViewControllerWithIdentifier("SignupNavigationController") as! UINavigationController
let landingPageVC = storyboard.instantiateViewControllerWithIdentifier("LandingPage") as! LandingPageViewController
presentViewController(signupVC, animated: true, completion: {
UIApplication.sharedApplication().delegate?.window??.rootViewController = landingPageVC
UIApplication.sharedApplication().delegate?.window??.sendSubviewToBack(landingPageVC.view)
})
When I close my modal view controller it's the previous rootViewController that is displayed (only during the animation). Then my new view controller is displayed properly.
Any idea how I could prevent this ?
Answering to myself,
The view I can see during the modal animation is something like a snapshot. I found out that the view is not visible in Xcode's view hierarchy debugger, thus the view is not present in the viewController tree.
To refresh this snapshot I had to set the modalPresentationStyle to .OverFullScreen
myModalViewController.modalPresentationStyle = .OverFullScreen

Resources