ios swift method to navigate through viewcontroller programatically - swift

i would like create my function to navigate through my views.
i have a function
func ShowView(name:String,caller:AppDelegate){
//story board
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let initViewController: UIViewController = storyBoard.instantiateViewControllerWithIdentifier(name) as UIViewController
caller.UIWindow?.rootViewController = initViewController
}
but i need to call this function from AppDelegate and UIViewController , how can i get uiwindow from UIViewController , from AppDelegate is ok but i can't keep AppDelegate like caller parameter cause i would like that it work with UIViewController.
I don't really know which i must use for my parameter.
many thanks

You don't need to replace rootView Controller every time if you are moving from master to details views. Connect root view to details view using segue. Set a identifier to segue in your storyboard. Overide prepareForSegue in your viewController class.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if(segue.identifier == "showDetails")
{
var viewController=segue.destinationViewController as DetailsView
//set data
}
}

Related

Make a segue to a tableview controller from a view controller

I am trying to make a segue to a table view controller when a button is tapped in my view controller programmatically. Here is my code:
#objc func editProfileButtonAction(sender: UIButton!) {
print("ButtonTapped")
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let identifier = segue.identifier {
if identifier == "EditProfile" {
var editProfileTableViewController = segue.destination as! EditProfileTableViewController
editProfileTableViewController = self
}
}
}
}
I really could use some help. I also need to make a segue to a collection view controller using a button in the same view controller.
Okay to clarify that. There is no way to create a segue programmatically. Segues are the arrows on storyboard linking from one to another VC. They are called with: performSegue. This calls the function prepare.
If you want to show a new VC when hitting a button (without segue), then you use the present(VC(), animated: true, completion: nil) } inside the button function. The VC is presented modally.
#objc func editProfileButtonAction(sender: UIButton!) {
print("editProfileButtonAction")
present(EditProfileTableViewController(), animated: true, completion: nil)
}
Make sure, that the segue in the Storyboard has exactly the identifier: "EditProfile". Normally I'm writing identifiers with lower letter in the beginning. You also need to prepare for Segue. For example set the delegate:
// Set ViewController class as the delegate of the EditProfileTableViewControllerDelegate protocol
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let identifier = segue.identifier {
if identifier == "EditProfile" {
let editProfileTableViewController = segue.destination as! EditProfileTableViewController
editProfileTableViewController = self
}
}
}
At one point in my coding time, I deleted all my storyboard because of too many error's that I could hardly solve. Now I'm doing it all programmatically. At first it was a bit hard to set up all the view's by myself but after all I'm very glad I'm not using storyboards anymore. For some stuff I need xib's, and for testing storyboard. Just if you're interested: the most iOS programmers are using storyboard, so it's okay if you go on with that.
The advantage of doing it all programmatically is that there are no segue's anymore. So just present, and on navigation VC's push, pop, ...

Cocoa swift load ViewController and and storyboard view from AppDelegate

I have created a SideBar() class which creates a NSView with various buttons.
I instantiate my sideBar() in my AppDelegate by doing
func applicationDidFinishLaunching(_ notification: Notification) {
sideBarView.setupSideBarView()
sideBarView.menuButton.action = #selector(self.NewMenuButton(_:))
}
#objc func NewMenuButton(_ sender: NSButton) {
}
In my Initial ViewController I then present my sideBar in the following way:
view.addSubview(sideBarView.getView())
With the press of menuButton I would like the function in the App Delegate to load and present a new storyboard view with its ViewController.
Can this be done?
Thanks.
I solved the issue giving my second ViewController a storyboard id.
Then, through the AppDelegate function:
let storyboard = NSStoryboard(name: NSStoryboard.Name("Main"), bundle: Bundle.main)
let mainPageController = storyboard.instantiateController(withIdentifier: "test") as! SecondViewController
NSApplication.shared.mainWindow?.contentViewController = mainPageController

Swift - resetting vc in nav controller that is embedded in tab bar

I have a customerViewController that has a simple a form. When the user presses submit, a segue is triggered and another view appears. The problem occurs when the user goes back to the customerViewController and finds all of the old information still there. I could simply reset the form fields, but what I'd really like is to find a way to reset the entire VC. From what I've learned so far, the way to reset a vc that hasn't been pushed is to remove it and then add it back.
customerViewController is the initial view controller in a navigation controller which is embedded in a tab bar controller. I have a tabBarController class that is a UITabBarControllerDelegate. This is where I call:
override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
if item.tag == 2 { //This is the tab with my navigation controller
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "CustomerVCID")
var viewcontrollers = self.navigationController?.viewControllers
viewcontrollers?.removeFirst()
viewControllers?.insert(vc, at: 0)
self.navigationController?.setViewControllers(viewcontrollers!, animated: true)
}
The problem with my code is that navigationController?.viewControllers is nil in the code above. I can reference viewControllers which gives me a list of tab bar viewControllers, but I'm not sure how to get from there to the navigation controller.
I guess my question is, assuming that I'm on the right track, how do I reference the view controllers in my navigation controller?
You can reset your form values in vc inside the viewWillAppear(_:),
class ViewController: UIViewController {
override func viewWillAppear(_ animated: Bool) {
//clear the textfields, textviews values etc. here.
}
}
It turns out, I was over-complicating things by trying to access navigationController.viewControllers or tabBarController.viewControllers. All I needed was viewControllers which is a property of UITabBarController that contains an array of the controllers associated with each tab:
override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
if item.tag == 2 { //tab with navigation controller
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vcon = storyboard.instantiateViewController(withIdentifier: "CustomerVCID")
for viewcontroller in viewControllers! {
if let vc = viewcontroller as? UINavigationController {
vc.viewControllers.removeFirst()
vc.viewControllers.insert(vcon, at: 0)
vc.setViewControllers(vc.viewControllers, animated: true)
}
}
}

Navigate from a controller to another controller having a root controller between them

I have 3 controllers: RootController, FirstController and SecondController.
I want to navigate from RootController -> FirstController (here I press a button) -> Take me to SecondController.
How can I do this without Notifications and Observers and without to create a segue from that button to SecondVC because after I need to press < Back and again < Back.
This is what I've tried to do but is not working:
import UIKit
class FirstViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func goToSecondVC(_ sender: UIButton) {
// Go from first VC to second VC
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let showSecondVC = storyBoard.instantiateViewController(withIdentifier: "goSecondVC") as! SecondViewController
self.present(showSecondVC, animated:true, completion:nil)
}
}
For your code example to work your SecondViewController needs to have the Storyboard ID set to "goSecondVC". This is done in the Identity inspector in the third tab in the right pane. This will present your ViewController modally. However since you have a navigationController you most likely want to push the SecondViewController on the navigationStack like so:
navigationController?.pushViewController(secondVC, animated: true)

Swift: How do you pass information to a view controller underneath the current one?

I have two view controllers, HomeViewController, and SecondViewController, which is pushed on top of HomeViewController at the top of the stack. I have a segue from HomeVC to SecondVC by means of 'Show'. I understand how to pass information from SecondVC to HomeVC - using the prepare for segue method using identifiers. But I do not have a segue from SecondVC to HomeVC, as it is embedded in a navigation controller. How would I pass information, for example a string, from SecondVC back to HomeVC upon popping the SecondVC from the navigation stack?
You need to pass a ViewModel from the HomeViewController to the SecondViewController, what you do is give your Segue an Identifier and then override prepareForSegue in your HomeViewController:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
if segue.identifier == "mySegueIdentifier" {
if let destination = segue.destinationViewController as? SecondViewController {
destination.aViewModel = aViewModel;
}
}
}
In your SecondViewController you need to declare the ViewModel:
class SecondViewController: UIViewController {
var aViewModel: AViewModel?
//rest of code
}
And create a ViewModel, use a struct type:
struct AViewModel
{
let AValueIWantToPassAround: String
let AnotherValueIWantToPassAround: Int
}