I'm currently using a third party called "Form".
In my UIButton, I implement a method which initializes a custom view controller which is a subclass of FormViewController. I initialize FormViewController embedded in navigation controller.
In my FormViewController class, I tried below two methods but none of them did not work.
self.navigationController?.popViewControllerAnimated(true)
self.dismissViewControllerAnimated(true, completion: nil)
Codes for pressing a UIButton:
#IBAction func part1Pressed(sender: AnyObject) {
if let JSON = NSJSONSerialization.JSONObjectWithContentsOfFile("data.JSON") as? [String : AnyObject] {
let initialValues = [
"last_name" : "Nordman"]
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let viewContainerVC = storyboard.instantiateViewControllerWithIdentifier("viewContainerVC")
let sampleController = Part1_VC(JSON: JSON, initialValues: initialValues)
let rootViewController = UINavigationController(rootViewController: sampleController)
rootViewController.view.tintColor = UIColor(hex: "5182AF")
rootViewController.navigationBarHidden = false
FORMDefaultStyle.applyStyle()
FORMSeparatorView.appearance().setSeparatorColor(UIColor.clearColor())
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
self.window?.rootViewController = rootViewController
self.window?.makeKeyAndVisible()
}
}
Thank you!
You are trying to dismiss the view controller when it wasn't presented in the first place.
Instead set the root view controller of the navigation controller to something else (e.g. the screen you want shown after you dismiss the form) and present your form view controller modally:
self.presentViewController(formVc, animated: true, completion: nil)
You can then dismiss the view controller as you intended when you are finished with the form.
Related
I'm working on a project, the project doesn't have storyboards, it just have a views as xib files with its own class , the question is : how can I navigate between these xib views ?
or is it possible to embed them in navigation controller ?
I try this code but nothing happened ?
let NC = UINavigationController()
#IBAction func showUserProfile(_ sender: Any) {
print("show Profile")
let vc = UserProfile(
nibName: "UserProfile",
bundle: nil)
NC.pushViewController(vc,
animated: true )
}
this is in app delegate
let mainView = BlockListViewController(nibName: "BlockListViewController", bundle: nil)
window?.addSubview(mainView)
let navigationControll = UINavigationController(rootViewController: mainView)
self.window?.rootViewController = navigationControll
self.window?.makeKeyAndVisible()
and I try to navigate when event occur using this
self.navigationController?.pushViewController(UserProfile(), animated: true)
You can't navigate between instances of UIView
according to apple UINavigationController
A container view controller that defines a stack-based scheme for navigating hierarchical content.
A navigation controller is a container view controller that manages
one or more child view controllers
so basically a stack of UIViewController, defined as [UIViewController]
read more about it in the documentation
What you can do is adding each UIView in a UIViewController and navigate thru that simply.
According to your comment you can predefined them into instance of VC and create a UINavigationController with you'r initial then simply push to the desired UIViewController from the UINavigationController
COMMENT UPDATE
As I got from your comment in the main view you already defining the UINavigationController simply replace NC.pushViewController(vc,animated: true )
with self.navigationController.pushViewController(vc, animated: true )
The problem is you are creating new UINavigationController while you already have the first one embedded
Comment update:
if you're using iOS 13+ with scene delegate use this inside willConnectTo
guard let scene = (scene as? UIWindowScene) else { return }
// Instantiate UIWindow with scene
let window = UIWindow(windowScene: scene)
// Assign window to SceneDelegate window property
self.window = window
// Set initial view controller from Main storyboard as root view controller of UIWindow
let mainView = BlockListViewController(nibName: "BlockListViewController", bundle: nil)
let navigationControll = UINavigationController(rootViewController: mainView)
self.window?.rootViewController = navigationControll
// Present window to screen
self.window?.makeKeyAndVisible()
and call self.navigationController.push
like this
#IBAction func didTap(_ sender: UIButton) {
let secondView = secondVC(nibName: "secondVC", bundle: nil)
self.navigationController?.pushViewController(secondView, animated: true)
}
Let's say I have three view controllers. On the first one, I tap a button and present the second view controller modally. On the second one, I tap a button and store the presenting view controller (first), then set the third view controller as the root view controller. Finally, I have a button on the third view controller that grabs the stored controller and sets that as the root view controller.
When I restore the first view controller, I find that its presentedViewController property is nil. I wonder if I can preserve the navigation stack and have the modal presented when I restore the first view controller?
In this example I'm storing the view controller inside AppDelegate for simplicity.
Code:
FirstViewController.swift
#IBAction func presentViewController(_ sender: Any) {
let storyboard = UIStoryboard(name: "SecondVC", bundle: nil)
let controller = storyboard.instantiateViewController(withIdentifier: "Second")
present(controller, animated: true, completion: nil)
}
SecondViewController.swift
#IBAction func secondButtonCLick(_ sender: Any) {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.savedVC = presentingViewController
let storyboard = UIStoryboard(name: "Third", bundle: nil)
let controller = storyboard.instantiateViewController(withIdentifier: "ThirdVC")
UIApplication.shared.keyWindow?.rootViewController = controller
}
ThirdViewController.swift
#IBAction func thirdBtnTouch(_ sender: Any) {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let rootVC = appDelegate.savedVC
UIApplication.shared.keyWindow?.rootViewController = rootVC
}
I have a few view controllers with navigation bar and tab bar. Then I have an initial view controller with no navigation bar and tab bar. I want to go back to the initial view controller with no other view controllers in stack. Here's what I do:
// Head back to Initial View Controller.
let initialViewController = self.storyboard!.instantiateViewController(withIdentifier: "Initial")
UIApplication.shared.keyWindow?.rootViewController = initialViewController
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.window?.rootViewController = initialViewController
This works perfectly. But then it doesn't move to another view controller from the initial view controller again. For example:
#IBAction func loginButton(_ sender: Any) {
print("Login Button Tapped.")
let storyboard = UIStoryboard(name: "SignInViewController", bundle: nil)
let signInViewController = storyboard.instantiateViewController(withIdentifier: "SignInViewController") as! SignInViewController
self.navigationController?.show(signInViewController, sender: nil)
}
Here, the print statement is run, but self.navigationController.show won't. How do all this work? And what's the right approach to accomplish this?
EDIT:
To avoid any confusion, here's my storyboard. The left most viewcontroller (pink screen) is the initial view controller I want to go back to. The right most on the same level is the view where I want to go back from.
It doesn't move to another view controller, because you are setting a simple view controller in your rootViewController.
What you need is:
let initialViewController = self.storyboard!.instantiateViewController(withIdentifier: "Initial")
let navController = UINavigationController.init(rootViewController: initialViewController)
UIApplication.shared.keyWindow?.rootViewController?.present(navController, animated: true, completion: nil)
This will create a navigationviewcontroller, so when on "Initial" you should be able to perform push, present actions of another view controllers.
From your initial view controller, you need to instantiate your navigation stack and present it modally. Then, when you want to get back to your pre-navigation initial VC, just call dismiss(animated:,completion:), which will dismiss your entire navigation stack and return you to the initial view controller.
self.navigationController.popToRootViewController(animated:) is what you're looking for.
https://developer.apple.com/documentation/uikit/uinavigationcontroller/1621855-poptorootviewcontroller
EDIT
Try dismissing the navigationController after calling popToRoot.
self.navigationController.dismiss(animated: true, completion: nil)
EDIT
Try the following:
#IBAction func loginButton(_ sender: Any) {
print("Login Button Tapped.")
let storyboard = UIStoryboard(name: "SignInViewController", bundle: nil)
let signInViewController = storyboard.instantiateViewController(withIdentifier: "SignInViewController") as! SignInViewController
present(signInViewController, animated: true, completion: nil)
//self.navigationController?.show(signInViewController, sender: nil)
}
Then to dismiss the signInViewController call self?.navigationController.dismiss(animated:true, completion:nil) from inside the signInViewController.
My goal is whenever i click a button on a first view controller, then it will navigate to another controller which is a navigation controller.
firstViewController and secondViewController has no connection or anything.
Picture
I used this code
#IBAction func buttonTapped(sender: UIButton) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("secondViewCtrl") as! SecondViewController
self.presentViewController(vc, animated: true, completion: nil)
}
The reason why i instatiate so that I could pass data like
vc.name = "Myname"
The problem with this code is that it doesn't present navigation bar and as well as the tab bar. What should I do to show both?
Updated question
#IBAction func buttonTapped(sender: UIButton) {
guard let tabBarController = tabBarController else { return }
tabBarController.selectedIndex = 1
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("trackYourGenie") as! TrackYourGenieViewController
let navController = tabBarController.viewControllers![1]
let secondViewController = navController.topViewController
vc.name = "Myname"
}
You are instantiating the view controller hence you wouldn't get the navigation bar. To get the navigation bar please instantiate navigation controller and since the second view is only child you would get the second view by default.
#IBAction func buttonTapped(sender: UIButton) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("Navigation Controller Id") as! UINavigationController
self.presentViewController(vc, animated: true, completion: nil)
}
The above code should give you the navigation bar.
A safe approach:
guard let tabBarController = tabBarController else { return }
tabBarController.selectedIndex = 1
If you need to access to your tabBarController to pass datas you can do simply:
let navController = tabBarController.viewControllers[1]! as! UINavigationController
let secondViewController = navController.topViewController
Your method could be:
#IBAction func buttonTapped(sender: UIButton) {
guard let tabBarController = tabBarController else { return }
let navController = tabBarController.viewControllers[1]! as! UINavigationController
let secondViewController = navController.topViewController as! SecondViewController
secondViewController.name = "my name"
tabBarController.selectedIndex = 1
}
In your case, the following code should be sufficient :
self.tabBarController.selectedIndex = 1
As UITabBarController is your rootViewController, you can access it with self.tabBarController. You don't have to instantiate UINavigationController as it is in the storyboard.
I can see from your StoryBoard that you have a TabBarController. If your configuration is that and FirstViewController is on first tab and SecondViewController on second tab, you can just change TabBarController selectedIndex property:
#IBAction func buttonTapped(sender: UIButton) {
tabBarController?.selectedIndex = 1
}
If you want to pass data to SecondViewController you can try one of these solutions:
let controller = tabBarController.viewControllers[1] as SecondViewController!
controller.data = "some data"
This soultion could not work since SecondViewController is not ready yet.
Create a singleton class where to save data, then retrieve data in SecondViewController viewDidLoad method
Save data in UserDefaults, then retrieve data in SecondViewController viewDidLoad method (bad solution if information doesn't have to be persistent)
Extend UITabBarController and use it, create a custom var in tabBarController, put data in that variable and then retrieve data in SecondViewController viewDidLoad method
Then clear data if needed.
Navigation will not work from firstViewController as to navigate something we need UINavigationController.
Try Like This
I'm trying to want to present/push a VC embedded in a NavController from AppDelegate. I previously used this code but somehow it's not working anymore:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let VC = storyboard.instantiateViewControllerWithIdentifier("PendingRequest") as! PendingRequestVC
let navController = UINavigationController.self(rootViewController: VC)
let rootViewController = UIApplication.sharedApplication().keyWindow!.rootViewController
rootViewController!.presentViewController(navController, animated: false, completion: nil)
Other codes open my desired VC but not within a navigation pane. Any guidance would be appreciated.
Calling from AppDelegate after user interacts with push notification.
Edit:
I'm able to present the right VC by using this code:
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
if let viewController = mainStoryboard.instantiateViewControllerWithIdentifier("PendingNavController") as? UINavigationController {
if let yourViewController = viewController.topViewController as? PendingRequestVC {
//yourViewController.getRequestdata()
}
UIApplication.sharedApplication().keyWindow!.rootViewController = viewController;
}
But this code won't allow me to go back using the Close button on my NavBar.
My structure is as follow:
TabController -> NavController1 -> VC1 -> NavController1a -> VC1a
I'm trying to get to VC1a and be able to use the Closed button to go back to VC1
Add a UIButton in your presented ViewController's View. Following event will be performed by that button. You can dismiss your Navigation Controller this way
#IBAction func dismissViewController(sender: AnyObject) {
self.navigationController.dismissViewControllerAnimated(false, completion:nil);
}