swift3 how to show navigation viewcontroller - ios

I would like to open the specific view from the notification widget.
normally other answers are create new view..(let viewcontroller = ... )
so If you continue to call, continue use memory..
So, I want to open viewA, which is already opened in my app, and then move to viewB.
My application structure is basically a viewA when the application is launched.
What I think is that instead of creating a new viewA, I want to move to viewB using the navigation.push from the already existing viewA.
The way to check whether a particular page already exists, how to show that page at the top , and how to navigation.push is work.
now i'm using this code to open viewA from Appdelegate
let MainView: Main_View_List_ = mainStoryboard.instantiateViewController(withIdentifier: "Main_List_View") as! Main_View_List_
let nav = UINavigationontroller.init(rootViewController: MainView)
UIApplication.topViewController()?.present(nav, animated: true, completion: nil)

Assuming you have access to the navigation controller, you'll want to do something like this to pop back to viewA:
for viewController in nav.viewControllers {
if viewController is ViewAClass {
viewController.pushViewBFlag = true
nav.popToViewController(viewController, animated: true)
return
}
}
Once you get back to viewA, you can check for pushViewBFlag and create and push viewB.
Alternately, since it seems that you are setting viewA as the root of your navigation controller, you could do: nav.popToRootViewControllerAnimated(true) to get back to viewA. You would need to then handle pushing viewB from viewA.

Related

Add and Edit Data using Single View Controller?

I am a beginner, I am trying to add and edit data using a single view controller, process works fine, but when I try to click add button, view controller is pushed twice.
When I try to Open Click
But When I click Back in the navigation bar, the Screen appears with my designs.
Code For Launching Add Screen
let MenuAdd = self.storyboard?.instantiateViewController(identifier: "MenuEdit") as! AdminMenuVC
MenuAdd.IsEdit = true
self.navigationController?.pushViewController(MenuAdd, animated: true)
Code For Launching Edit Screen
let MenuEdit = self.storyboard?.instantiateViewController(identifier: "MenuEdit") as! AdminMenuVC
MenuEdit.IsEdit = true
self.navigationController?.pushViewController(MenuEdit, animated: true)
There are possible explanation for this:
You also have a storyboard segue going from the add button to the AdminMenuVC- if this is the case, just delete it (you are already pushing it from code)
You call from the first VC both self.navigationController?.pushViewController(MenuAdd, animated: true) and self.navigationController?.pushViewController(MenuEdit, animated: true) - they both refer to the same VC (AdminMenuVC). I cannot say if this is the case as you haven't posted the code. Be careful to check that you are not calling the two lines of code at the same time
Check button action you may be setting action and touch up inside actions on same button. You need to remove one action from reference inspector

How can I push two VC but only presenting top VC

I would like to emulate contact list in ios. When one taps + button to add contact, a new view controller is presented that gives you textfields to enter contact name and additional info for saving about that contact. Once you tap Done button, the next view controller presented already seems to be embedded in a navigation controller with the button that takes you back to the contact list. I've tried code found on here but it pushes 3 view onto navigation stack
//first attempt
var controllers = navigationController?.viewControllers
controllers?.append(secondVc)
controllers?.append(thirdVC)
navigationController?.setViewControllers(controllers!, animated: true)
//second attempt
let pushVC = UIViewController()
let backVC = UIViewController()
if let navigationController = navigationController {
navigationController.pushViewController(pushVC, animated: true)
let stackCount = navigationController.viewControllers.count
let addIndex = stackCount - 1
navigationController.viewControllers.insert(backVC, atIndex: addIndex)
}
I've also tried other combinations that look cringy. Here is what I want it to look like: https://imgur.com/a/IAJ5G
This should work:
navigationController.pushViewController(secondVc, animated:false)
navigationController.pushViewController(thirdVc, animated:true)
Apple does the same by presenting a new window, with the form to create a new contact.
After making the new window as the keyWindow, they push the contact details VC on to the navigation controller on the original window. This push happens in the background, which the user is not able to witness.
You can view the same by attaching a debugger to the Contacts app.
Heres a screenshot of the view hierarchy. You will be able to see that there are no view controllers from the original window underneath the CNContactContentViewController.
When the user taps Done, the original window is restored as the keyWindow, and the contact details VC is updated to show the newly added contact.

When changing view controllers, new controller appears, but disappears almost immediately

I have this code in one of my IBAction (when a button is pressed), which is supposed to bring up a new view controller.
let addAlertVC = self.storyboard?.instantiateViewController(withIdentifier: "addAlert")
self.present(addAlertVC!, animated: false, completion: nil)
However, when I run the app and press the button that's supposed to take me to the new viewcontroller, but then I'm stuck with the original viewcontroller. I have put a print statement in the viewDidAppear function in the new view controller, and it is printing out whenever I press the button, so the new controller is definitely appearing. I have not dismissed the new controller anywhere in my app.
I have used the same code in other parts of my app, so I'm extremely confused as to why it's not working this time.
Any help would be greatly appreciated.
EDIT: I fixed my code. It turns out it wasn't how I was calling the view controller that was wrong, it was my button. Once I deleted and re-added the button, my code now works.
There is a good chance that your view controller is deallocated after you present it.
Try to declare your view controller outside of the function, in your controller. Something like:
class ViewController{
var addAlertVC:UIViewController?
...
func someFunction(){
addAlertVC = self.storyboard?.instantiateViewController(withIdentifier: "addAlert")
self.present(addAlertVC!, animated: false, completion: nil)
}
}

Clearing Navigation Stack in Swift

I'm currently designing an application that has a funnel flow and a dashboard flow. I'd like the funnel flow to be cleared from memory on completion:
So if it goes
1) if new user start funnel -> 2) funnel screens 1-5 -> 3) funnel complete screen
I'd like to transition to dashboard screen which is not yet on the stack (it's not my head controller in this case). How can I clear the 6 screens above from memory when I transition to dashboard - basically setting a new navigation root and clearing the rest? An unwind segue doesn't appear to be able to set a new root destination.
If you only want to clear the navigation stack, and push a new view on top of it, there is an even simpler solution.
Let's suppose you already (programmatically) assigned a navigation controller, e.g. in a viewDidLoad() function, like:
let navController = UINavigationController( rootViewController: YourRootController )
view.addSubview( navController.view )
addChildViewController( navController )
navController.didMoveToParentViewController( self )
YourRootController acts as the stacks's root (the bottom of the stack).
To push other controllers on top of the stack (your funnel controllers), simply use navController.pushViewController( yourControllerInstance!, animated: false ).
If you want to clear the stack after completion of the funnel, just call:
navController.popToRootViewControllerAnimated( false )
This function removes all views (besides the root controller) from your stack.
So I ended up having to do it programmatically by popping back to the first controller and then replacing from the funnel head to the dashboard head:
func bookingCompleteAcknowledged(){
//remove the popup controller
dismissViewControllerAnimated(true, completion: nil)
//remove current controller
dismissViewControllerAnimated(true, completion: nil)
if let topController = UIApplication.sharedApplication().keyWindow?.rootViewController {
if let navcontroller = topController.childViewControllers[0] as? UINavigationController{
navcontroller.popToRootViewControllerAnimated(false)
if let funnelcontroller = navcontroller.childViewControllers[0] as? FunnelController {
funnelcontroller.removeFromParentViewController();
funnelcontroller.view.removeFromSuperview();
let revealController = self.storyboard?.instantiateViewControllerWithIdentifier("DashboardController") as! SWRevealViewController
navcontroller.addChildViewController(revealController)
navcontroller.view.addSubview(revealController.view)
}
}
}
}
I believe you can do this by simply assigning a new array (with just the dashboard view, in your case) to the UINavigationController's viewControllers property.
Why do you want to use the same navigation controller instead of making a new one? Generally, instead of trying to change the root of a navigation controller, I would recommend just creating a new navigation controller.

How can I segue or pop back to the second scene of the first tab in a tabbed app, from a scene on another tab?

I have a storyboard set up with a tab bar controller and three tabs. Each tab has a navigation controller. The first tab has three scenes. There is a button (log out) in a view on the third tab that I would like to segue to the second scene on the first tab (corresponding to the log in view controller and connected to the first scene via Show(e.g., Push).
Here is what I've tried:
self.tabBarController?.selectedIndex = 0
This works, insofar as I get back to the first tab's initial scene after tapping the UIButton. But since I want to get to the second scene, this is not a complete solution. I think the solution may be along the lines of:
self.tabBarController?.selectedViewController = LoginViewController()
or
self.tabBarController?.setViewControllers(self.LoginViewController, animated: true)
But I do not want to create another instance of a view controller.
Can I still use .selectedIndex to implement a solution?
A simple solution u can try is
1. Set a Global variable (i.e in App Delegate) name as isLogoutClick of type boolean.
2. While you are on third tab and click on logout button then make the global variable "isLogoutClick" as true.
3.and then navigate to first tab (1st scene) and on viewDidLoad just check the condition that
if(appDelegate.isLogoutClick)
{
push your view to next scene.
}
4. make false the value of isLogoutClick.
5. make sure at initially the value of isLogoutClick is false.
try this might it will help you.
After setting selectedIndex to 0, perform the segue you want (in this example, "loginSegue"). You can name your segue in the storyboard if you haven't already.
tabBarController?.selectedIndex = 0
if let someViewController = tabBarController?.viewControllers?[0] as? SomeViewController {
someViewController.performSegueWithIdentifier("loginSegue", sender: nil)
}
I'm not sure if this works for tabBarController because I've used this for my navigationController but should work the same.
if let tab = self.tabBarController?.viewControllers {
if let index = find(tab.map { $0 is LoginViewController }, true) {
let destination = tab[index] as LoginViewController
tabBarController?.presentViewController(destination, animated: true, completion: nil)
}
}
With a navigationController I would use popToViewController but I'm not sure how the tabBarController exactly works

Resources