How To Remove The First ViewController In The Background? - ios

I have two view controllers, first view controller and the second view controller, when the user segue from the first view controller to the second view controller, the first view controller still visible and sits behind the second view controller. The user can swipe the first view controller and see the entire first view controller and then they got stuck there. I noticed that this only happens after the launch of iOS 13.
performSegue(withIdentifier: "showSecond", sender: self)

Follow these two steps:
Click on the segue you created on the Storyboard
Go to Attributes Inspector
Set the Presentation to "Full Screen"

#Maysam is 100% right! But you can also do it programmatically through this:
// Go to next View Controller
#IBAction func nextTextVC(_ sender: UIButton) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let nextInfo = storyboard.instantiateViewController(identifier: "socialOptionsIntroViewController")
self.navigationController?.pushViewController(nextInfo, animated: true)
}

There is a more detail thread could answer this question.
The follow solution from Pratik Sodha
let controller = UIViewController()
let navigationController = UINavigationController(rootViewController: controller)
navigationController.modalPresentationStyle = .overCurrentContext
self.navigationController?.present(navigationController, animated: true, completion: nil)

Related

Segueing to New View Controller while Dismissing previous without navigation controller: swift

Hello I am pretty annoyed with this:
Originally, I had many segues in my storyboard. Each button at bottom of tool bar would segue to various view controllers. As you can imagine, that is a lot of segues for 6 different items on toolbar. After segueing, each action would call self.dismiss and everything would be ok.
Recently, I wanted to clean up the storyboard.
I created the function:
extension UIViewController {
func segue(StoryboardID: String) {
let popOverVC = UIStoryboard(name: "Main", bundle:
nil).instantiateViewController(identifier: StoryboardID)
popOverVC.modalPresentationStyle = UIModalPresentationStyle.fullScreen
popOverVC.modalTransitionStyle = .crossDissolve
self.dismiss(animated: false, completion: nil)
print("dismissed")
self.present(popOverVC, animated: false, completion: nil)
print("presented")
}
}
What I am seeing is that the dismiss dismisses the new view controller from appearing. It essentially goes back to my first view controller presented upon launch. I want to dismiss all view controllers so that I don't keep piling up my views.
Thanks
The problem is that you present your popOverVC from a view controller that is being dismissed, so your popOverVC will never be shown as its parent is being dismissed.
Not sure how your architecture is exactly but you would either need to use the delegate pattern to tell the parent when to segue, for example:
self.dismiss(animated: true) {
self.delegate?.didDismiss(viewController: self)
}
Or to use some trick to get the top most view controller to present your popOverVC after the current view has been dismissed, ex:
self.dismiss(animated: true) {
var topController: UIViewController = UIApplication.shared.windows.filter{$0.isKeyWindow}.first!.rootViewController!
while (topController.presentedViewController != nil) {
topController = topController.presentedViewController!
}
topController.present(popOverVC, animated: true)
}
But I agree with #Paulw11, a UITabBarController seem like a much better option for what you're trying to do.

Setting back button when presenting a view controller

On clicking a button I display a view controller using the following code:
let navController = UINavigationController(rootViewController: locationVC)
navController.navigationBar.barTintColor = StyleHelper.navBarColor()
navController.navigationBar.tintColor = UIColor.whiteColor()
navController.navigationItem.backBarButtonItem = UIBarButtonItem(image: UIImage(named: "back_arrow"), style: .Plain, target: locationVC, action: nil)
self.presentViewController(navController, animated: true, completion: nil)
But the back button does not appear on the locationVC
What am I doing wrong? Please help
Multiple issues with code.
Issue 1:
You should update viewController's bar button item and not navigationController's bar button item.
So this is wrong
navController.navigationItem.backBarButtonItem
Whats correct
self.navigationItem.backBarButtonItem
Issue 2:
The above code won't work because your current viewController is not pushed by any other VC so it cant show back button. What you need is leftBarButtonItem
So in your VC you can write
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Abcd", style: .done, target: self, action: yourSelectorHere)
}
O/P:
Back button only appears for view controllers in the navigation stack.
you creating new navigation controller stack and making locationVC as root controller so there won't be any view controller to go back.
If you push another view controller to the navigation stack then you will get back button.
In a horizontally regular environment, the view controller is
presented in the style specified by the modalPresentationStyle
property. In a horizontally compact environment, the view controller
is presented full screen by default. doc: presentViewController
So, if you use present a view controller it will not show in navigation controller thus no back button
For this case you need to push view controller.
From storyboard:
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyBoard.instantiateViewController(withIdentifier:
"newViewController") as! YourViewController
self.navigationController?.pushViewController(vc, animated: true)
Programmatically
let vc = YourViewController()
self.navigationController?.pushViewController(vc, animated: true)
presenting will present your VC on top of everything and not push it to the navigayionCOntroller.
You should push your VC to the NavigationController instead like so:
var rootViewController = self.window!.rootViewController as UINavigationController
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
var profileViewController = mainStoryboard.instantiateViewControllerWithIdentifier("profile") as ProfileViewController
rootViewController.pushToViewController(profileViewController, animated: true)
presentViewController is a method that bring a modal view to your navigation, not part of the navigationController.
Instead you should use the pushToViewController method on the navigationController (and not creating a new one) like that :
if let navigationController = self.navigationController {
navigationController.pushViewController(locationVC, animated: true)
}
The presenting view controller is responsible for dismissing the view controller is presented. If you call this method on the presented view controller itself, UIKit asks the presenting view controller to handle the dismissal.
If you present several view controllers in succession, thus building a stack of presented view controllers, calling this method on a view controller lower in the stack dismisses its immediate child view controller and all view controllers above that child on the stack. When this happens, only the top-most view is dismissed in an animated fashion; any intermediate view controllers are simply removed from the stack. The top-most view is dismissed using its modal transition style, which may differ from the styles used by other view controllers lower in the stack.
If you want to retain a reference to the view controller's presented view controller, get the value in the presentedViewController property before calling this method.
#IBAction func backButtonAction(_ sender: UIButton) {
self.dismiss(animated: true)
}
More: https://developer.apple.com/documentation/uikit/uiviewcontroller/1621505-dismiss

TabBar disappears when programatic segue

I want to segue to a new ViewController programatically but when I do my tabBar disappears.
if user == usernameStored && pass == passwordStored{
print("Good")
let vc = self.storyboard?.instantiateViewController(withIdentifier: "home")
self.present(vc!, animated: true, completion: nil)
}
From your code, this is not segue by programmatically. You actually present a viewController on top of whatever you have. Therefore the tabBarController is cover.
To use segue in code, it should be something like this. - homeSegueID is the identifier you give when you created the segue in storyboard.
performSegue(withIdentifier: "homeSegueID", sender: nil)
If you just want to do it programatically without segue, you could do this instead. (This assume your current ViewController is in a UINavigationController stack.
navigationController?.pushViewController(vc, animated: true)
Is the navigation controller wrapping your view controllers a tab bar controller, or did you just add the tab bar to your view controller? This is what you should be doing:

iOS Swift, returning to the same instance of a view controller

I have a problem, where I have two view controllers A and B. View controller B has a map, with a route draw on it. I can move back and forwards between the two view controllers at the moment, but the B view controller is reset every time it loads. I think this is because I am using segues and it is creating a new instance of a View controller every time.
I have tried using the following code to solve this issue, but it is still not working. The views load correctly, but view controller B is still being reset
#IBAction func mapButton(sender: AnyObject){
let storyboard = UIStoryboard(name: "MainStoryboard", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("SecondViewController") as! UIViewController
self.presentViewController(vc, animated: true, completion: nil)
}
What am I doing wrong and how can I fix it? I want view controller B to stay in the memory along with the map and the route, so when a user returns he doesn't have to enter all of the information again.
You should create a variable in your class of type UIViewController and change your code to the following:
#IBAction func mapButton(sender: AnyObject){
if yourVariable == nil {
let storyboard = UIStoryboard(name: "MainStoryboard", bundle: nil)
yourVariable = storyboard.instantiateViewControllerWithIdentifier("SecondViewController") as! UIViewController
}
self.presentViewController(yourVariable, animated: true, completion: nil)
}
That way you create the viewController one time, save it and if you want to open it again present the previously created one.

iOS: Go back to previous view

I have two views like this in Story Board:
[View1] -> [Navigation Controller] -> [View2]
To go from View1(has tableview) to View 2, i do this on click of a row on View1:
self.performSegueWithIdentifier("showmyview2", sender:self)
This works.
Now i have a button on View 2, which when clicked should take me back to previous view i.e View 1.
I tried this:
navigationController!.popViewControllerAnimated(true)
But this does not work. How do i go back to first view?
First Add a navigation controller to your First view1 through storyboard.(Editor->Embed Navigation controller), If navigation is not present.
OR
self.dismissViewControllerAnimated(true, completion: nil);
Call this function and try instead of navigation popviewcontroller
Use this code to present first view in your button action:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("FirstView") as! TableViewController
self.presentViewController(vc, animated: true, completion: nil)
And don't forget to give Id to your First view.
Select your firstView into storyBoard and then click on Identity Inspector and you can assign StoryBoard ID like show into below Image.
self.dismiss(animated: true, completion: nil);
this will work in swift 3

Resources