Xcode all segues show up the same - ios

I'm having some trouble going from my login VC which is a collectionVC to my main vc which is a navigation controller. No matter what type of segue I choose, i get this gap at the top where you can see the previous login VC, with the possibility to drag from the top of the current navigationVC to dismiss it. I've tried using all the different segues but they all show up like this for some reason. My loginVC has a login button, and changes to the navigation VC with the following code:
// Login user
func loginUser() {
Auth.auth().signIn(withEmail: emailTxtFld.text!, password: PasswrdTxtFld.text!) { (user, error) in
if error != nil {
print(error!)
} else {
print("Login succesfull!")
self.performSegue(withIdentifier: "goToMain", sender: self)
}
}
}
#IBAction func loginBtnTapped(_ sender: Any) {
loginUser()
}
I've connected the loginVC to the main VC with a segue, not the login button itself. The first slide of the navigation VC is a collectionview, the second is blank.

This is not a problem of segue, it is a problem with the ModalPresentationStyle of the presented view controller that, from iOS 13, defaults to automatic.
This means that (most of the) view controllers will be presented in this fashion.
You just need to set this modal presentation style to fullscreen in one of this points:
when you instantiate the view controller
when you prepare for segue
or in the viewDidLoad of the viewController itself
in storyboard segue https://stackoverflow.com/a/56530134/8517882
in storyboard view controller https://stackoverflow.com/a/57546875/8517882

Thank you Enricoza for explaining this to me. Since I made a segue using the storyboard I was able to make the segue full screen by following the seccond answer in this post: Presenting modal in iOS 13 fullscreen

Related

how can i deallocate viewControllers in ios

I made some views ordering like Login -> Navigation Controller[Dashboard -> Detail]
In LoginViewController, There is Login Button and it has Action
#IBAction func loginTapped(_ sender: Any){
let mainNavigationController = storyboard?.instantiateViewController(withIdentifier: "MainNavigationViewController") as! MainNavigationViewController
present(mainNavigationController, animated: true, completion: nil)
}
In NagivationController
There are two Views,Dashboard and Detail
Detail View is pushed by segue action from Dashboard
and Dashboard has tab bar Item to logout
I know that when back button is tapped in Detail view, It doesn't deallocating Detail View. It just push back to Navigation Controller's Stack (Is it right...?)
but when i tapped Logout Button in Dashboard, I thought Navigation Controller which contains two views (Dashboard, Detail) should be deallocated
but it doesn't deallocated.
I set the deinit method in Navigation View Controller like this
deinit {
print("Main Navigation View Controller is deinited")
}
but it never called
How can i deallocate views that appear after login, when i tapped logout button
Sorry for poor syntax in English because i'm not Native

Swift 3 : Switch ViewControllers programmatically

I am creating an application which shows a PageVC: UIPageViewController as intro and guide to app.
After navigating through the intro, a Next Button leads to "SettingsVC" which is used to store default settings for the app.
Settings have to be chosen by the user initially although can be changed later.
PageVC ---> SettingsVC
A Save and a Cancel button on the SettingsVC leads to the MainVC of the app.
A button on MainVC leads to SettingsVC.
SettingsVC <---> MainVC
The app would work as follows:
if isFirstLaunch{
instantiate PageVC
}else{
instantiate MainVC
}
in PageVC
nextButtonPressedinPageVC{
instantiate SettingsVC
}
in SettingsVC
if saveButtonPressed && cameFromPageVC{
instantiate MainVC
}
if cancelButtonPressed && cameFromPageVC {
do Nothing
}
if saveButtonPressed && cameFromMainVC{
dismiss currentVC
}
if cancelButtonPressed && cameFromMainVC {
dismiss currentVC
}
in MainVC
if settingsButtonPressedinMainVC {
instantiate SettingsVC
}
I have made sure that if it is application's first launch, PageVC will be instantiated else MainVC will be instantiated.
How can I move between the viewControllers without a possible memory leak i.e. where to performSegue and where to dismiss current VC?
Please include code for reference.
There are many ways to do this, here is one that I find very straightforward because you can do most of the work in your Storyboard:
Think of your MainVC as the rootViewController and the other two as accessory views that will only temporarily be shown. The MainVC should always be your entry point, so set it as the initial VC in your Storyboard.
The other two should be displayed modally so that you can easily return to the MainVC by dismissing them, no matter how you opened them in the first place.
To do this, draw a segue from your MainVC button to the PageVC and name it "showPageVC". From the Next button in your PageVC, draw another segue to the SettingsVC. Now you need some code to handle the dismiss actions: put this snippet in your MainVC:
#IBAction func unwindToMain(segue:UIStoryboardSegue) {
}
This function is just a marker, so it doesn't need a body. It just enables you to create a unwind segue back to MainVC: For each of the buttons in SettingsVC, hold Ctrl and draw from the button to the right exit icon in the header of the SettingsVC storyboard scene and choose unwindToMain in the tiny black popup.
Now you only have to implement the logic to decide if you want to show the PageVC or not in viewDidAppear() of the MainVC. So the whole code would look something like this:
class MainVC: UIViewController {
var didDisplayPageVC = false
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if (didDisplayPageVC == false) {
performSegue(withIdentifier: "showPageVC", sender: self)
didDisplayPageVC = true
}
}
#IBAction func unwindToMain(segue:UIStoryboardSegue) {
}
}
The rest is in the storyboard. If this little proof-of-concept is working, you can go and configure the segues (you might want to remove the animation) etc.

dismiss two controllers Swift

I have this situation :
I have a first view controller , when tap on button in it I open in modal mode another view controller , in this view controller when I tap another button I open in modal view another view controller and in it there is a button and when I tap on it I want to go to first view controller without re-initialize it.
How do I do it?
This is the perfect situation for an unwind segue.
Put this in your first viewController (the one you want to return to):
#IBAction func backFromVC3(_ segue: UIStoryboardSegue) {
print("We are back in VC1!")
}
Then in the Storyboard in your 3rd viewController, control-drag from your button to the exit icon at the top of the viewController and choose backFromVC3 from the pop-up.
Now, when the user presses the button in VC3, both VC3 and VC2 will be dismissed and you will return to VC1.
If you are not using Storyboards, you can dismiss the viewControllers with code. Here is code for a button's handler to dismiss two levels of viewController:
func doDismiss(_ sender: UIButton) {
// Use presentingViewController twice to go back two levels and call
// dismissViewController to dismiss both viewControllers.
self.presentingViewController?.presentingViewController?.dismiss(animated: true, completion: nil)
}
Thanks all for reply and edited my question :)
I found 2 line code to resolved my problem:
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
appDelegate.window!.rootViewController?.dismissViewControllerAnimated(true, completion: nil).
And that work well.
Thanks very much

performSegueWithIdentifier doesn't work in a different ViewController

I have the following storyboard: Main Storyboard
In it, several custom View Controllers are programmatically embedded in the Scroll View. In one of them, a button is present and should trigger a segue to show the "hey" screen.
I have then wrote the following code:
#IBAction func addNewDateButtonDidTouched(sender :AnyObject) {
let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
let storyboardInit = mainStoryboard.instantiateViewControllerWithIdentifier("mainview")
storyboardInit.performSegueWithIdentifier("showNewDate", sender: self)
}
This #IBAction seems to reload the inital view controller and perform the segue correclty (Xcode doesn't return any error). But the "hey" screen doesn't show up and its viewDidLoad() doesn't load.
Any hint?
Instead of calling
storyboardInit.performSegueWithIdentifier("showNewDate", sender: self)
try
self.performSegueWithIdentifier("showNewDate", sender: self)
The storyboardInit in your code will instantiate a UIViewController that has an identifier "mainview".
But this UIViewController hasn't been added to the screen, when you're asking the controller to perform a segue.
So, I wouldn't do that. What I would do, to segue to the hey screen is either :
Create a segue from the current controller and just do this in the code : self.performSegueWithIdentifier
Instantiate the hey controller like this : instantiateViewControllerWithIdentifier, and then just do the self.presentViewController
So, to transition to a new controller, you have to start from the current controller.
if i understand your viewcontroller hierarchy correctly...
since the viewcontroller that contains the button to trigger the segue is a childviewcontroller of the viewcontroller that has the segue setup in storyboard i think you have to call presentingViewController?.performSegueWithIdentifier("showNewDate", sender: self).

Unwind segue doesn't work SWIFT

I have a navigation controller, with a table view. When I press a cell, the detail view controller opens.
In my root view controller I have :
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "detailview" {
var destination:DetailViewController = segue.destinationViewController as DetailViewController
destination.delegate=self
}
}
In my detail view controller I have a back button :
#IBAction func back() {
self.navigationController?.popViewControllerAnimated(true)
}
The issue is, after 2 go to and return, my app crashes when I go back on the root view controller pressing back button. The console doesn't give me errors. It just crashes.
I think I have forgotten to unwind the segue.
So in my detail view controller I added :
#IBAction func unwindToViewController(segue: UIStoryboardSegue) {
println("unwind function")
}
I connect this function to my back button with "exit" in my storyboard.
When I run my app, If I press on the back button, the console doesn't display my print "unwind function", so unwindToViewController isn't called. Why ?
And my app still crashes...
Your unwindToViewController method should be placed in your root viewController, then ctrl-drag from the button in the detailViewController to the Exit icon in InterfaceBuilder. Choose that method in the popup menu.
Another approach would be to declare a protocol with a function in the rootViewController that is called from the detailViewController. You already set the rootViewController as the delegate of the detailViewController. Within that function you call dismissViewController.
Swift answer...
I had a similar problem.
The func: "segueForUnwindingToViewController(toViewController: UIViewController, fromViewController: UIViewController, identifier: String?) -> UIStoryboardSegue" was never called.
Solution:
since I didn't have a "UINavigationController", because I simply embeded the app in a Navigation Controller, I created a UINavigationController subclass for the Navigation Controller and added the function named above on it. Now the app calls "segueForUnwindingToViewController"

Resources