Transition from a sign in ViewController to a UITabBarController - swift

So I am trying to transition from my sign in viewcontroller to my tabbarcontroller, after a successful login.
When I enter my login details and press the sign in button, I am redirected to the Appdelegate page with a signal SIGABRT error.
I tried using this code in my viewcontroller:
let mainPage = self.storyboard?.instantiateViewController(withIdentifier: "CustomViewController") as! CustomViewController
self.present(mainPage, animated: true, completion: nil)

What's in CustomViewController? If you're instantiating that one directly as a ViewController instead of as a UiTabBarViewController, I'm thinking you will need to add the Sub ViewControllers for each one of the Tabs manually. But it's difficult to be sure without looking at what you have in CustomViewController.

Have you tried to set the application's rootViewController to the UITabBarController instance?
For example, this would set application's rootViewController to the tab bar controller:
let mainPage = self.storyboard?.instantiateViewController(withIdentifier: "CustomViewController") as! CustomViewController
UIApplication.shared.keyWindow?.rootViewController = mainPage

Related

How to navigate between tabs "TabBarController" and transfer data between them?

this code works almost as it should, but it opens a second window on top of the main one, and not separately. How do I programmatically navigate to another view controller?
let tableVC = self.storyboard?.instantiateViewController(withIdentifier: "SaveTableViewController") as! SaveTableViewController
tableVC.titleText = alert.textFields![0].text ?? "Test"
tableVC.tabBarController?.selectedIndex = 1
//self.tabBarController?.showDetailViewController(tableVC, sender: self)
//self.present(tableVC, animated: true, completion: nil)
Your tabBarController have a viewControllers array. If you want to show a specific ViewController programmatically you could set the selectedViewController attribute of your tabBarController to an element out of the viewControllers array...
For more detail: https://developer.apple.com/documentation/uikit/uitabbarcontroller/1621172-selectedviewcontroller

How do I pop out a ViewController(like a modal) programmatically?

All:
I am doing a swift , cocoa macos app project with multiple ViewControllers in one storyboard.
I know if I do segue and link the segue from second ViewController to first ViewController.
I can pop out ViewController.
But what if I have a function and want to call another ViewController to present programmatically from first ViewController?
I search a lot of examples start with UIStoryBoard, but my Storyboard is NSStoryboard.
Could anyone hint me a little to start with?
my code:
func checkPassword(SystemMsg:String) -> String{
//print("x")
let storyBoard = NSStoryboard(name: "Main", bundle: nil)
let mainViewController : NSViewController = storyBoard.instantiateController(withIdentifier: "PasswordInput") as! NSViewController
//self.present(mainViewController, asPopoverRelativeTo: <#T##NSRect#>, of: sender, preferredEdge: NSRectEdge, behavior: <#T##NSPopover.Behavior#>)
return ""
}
And my viewController in storyboard look like(no segue,no link):
enter image description here
If anyone can guide me through this step by step would be appreciated.
I figure it out myself.
The most simple way contains 4 steps:
Identify your main ViewController and second ViewController in storyboard
Create your main ViewController with instantiateController
Create your second ViewController with instantiateController
use presentAsModalWindow or presentAsSheet to present secondController on main ViewController
first we need to Identify storyboard correctly:
Identify first storyboard , we need to click top blue cube and then name it in Storyboard Id area
Identify second storyboard , we need to click top blue cube and then name it in Storyboard Id area
example code:
func checkPassword(SystemMsg:String) -> String{
//print("x")
//let storyBoard = NSStoryboard(name: "Main", bundle: nil)
let mainViewController : NSViewController = self.storyboard?.instantiateController(withIdentifier: "MainController") as! NSViewController
let passwordInputViewController : NSViewController = self.storyboard?.instantiateController(withIdentifier: "PasswordInput") as! NSViewController
mainViewController.presentAsModalWindow(passwordInputViewController)
//Or
mainViewController.presentAsSheet(passwordInputViewController)
return ""
}
If I miss something please correct me gently.
reference: Transitioning between view controller, OS X
PS. if you want to pass value between ViewController, this is good reference : https://learnappmaking.com/pass-data-between-view-controllers-swift-how-to/#back-properties

How to instantiate a view controller programatically, without storyboard

Is there a way to instantiate a view controller programatically without using storyboard identifier. I want to push CNContactPickerController into my root view controller .
let controller = CNContactPickerViewController()
controller.delegate = self
navigationController?.present(controller, animated: true, completion: nil)
i did this but in contactPicker (delegate) i push a VC from storyboard where i save what info i want from that specific contact.
The problem: when i pop the last view controller i want to go on the CNConctactPickerControllerView but i go on the first view controller
i tried with dismiss but nothing happens..
The problem with doing this is that NONE of the UI for your view controller is created. What you are doing is simply instantiating an instance of the class. None of the corresponding UI is created, also your IBOutlets will be nil.
You have 2 options, either you use Interface builder and instantiate from the Nib or Storyboard, or you create ALL your UI manually in code.
For the sake of resuability you could create a static method on CNContactPickerViewController to handle the storyboard instantiation for you. See the following:
class CBContactPickerViewController: UIViewController {
static func fromStoryboard() -> CNContactPickerViewController {
return UIStoryboard(name: "foobar", bundle: nil).instantiateViewController(identifier: "CNContactPickerViewController") as! CNContactPickerViewController
}
}
You can then utilise this as follows:
self.present(viewController: CNContactPickerViewController.fromStoryboard(), animated: true, completion: nil)

Swift - How to pass UInavigationController and also pass variables

What is the best way to pass a UInavigationController and also pass variables to a new viewController. I know how to do one or the other but not both at the same time. Thank you in advance
this is my current code
func(){
let vc = storyboard?.instantiateViewControllerWithIdentifier("messagesViewController") as! UINavigationController
let posts = self.postList[indexPath.row]
//this is the var that i want to past
//vc.previousViewMessageId = posts.postKey
self.presentViewController(vc, animated: true, completion: nil)
}
If I understand you correctly, you have a view controller that can present a second VC. And this VC is embedded in a UINavigationController. What you don't know how to do, is to pass data from the first VC, to the navigation controller, then to the second VC.
Here is a brute force solution. It's not beautiful, but it works anyway.
Make your own UINavigationController subclass:
class DataPasserController: UINavigationController {
var previousViewMessageId: SomeType?
override func viewDidLoad() {
if let vc = self.topViewController as? YourSecondViewController {
vc.previousViewMessageId = self.previousViewMessageId
}
}
}
Now you can add a navigation controller in the storyboard, set its class to DataPasserController, and connect the second VC to it as its root view controller.
Now suppose you have got an instance of DataPasserController by calling instantiateViewControllerWithIdentifier, you can do this:
yourDataPasserControllerInstance.previousViewMessageId = posts.postKey
And present the instance!
To pass a value to your Navigation Controller's Root View Controller, you access viewControllers[0] and cast it to the class of your Messages View Controller (the controller that has the previousViewMessageId property):
func () {
let messagesNC = storyboard?.instantiateViewControllerWithIdentifier("messagesViewController") as! UINavigationController
let messagesVC = messagesNC.viewControllers.first as! MessagesViewController
messagesVC.previousViewMessageId = postList[indexPath.row].postKey
presentViewController(messagesNC, animated: true, completion: nil)
}
What you have there is simply presenting a view controller... You are skipping the navigation controller.
What you need to do is present the new view controller inside the navigation controller. Once you have done that, it will show correctly. You can also pass the variables after you've created the vc variable.
This presents the new viewController (vc) within the navigation controller...
self.navigationController?.pushViewController(vc, animated: false)
This sets the variable in the new viewController (vc) (you are correct)
vc.previousViewMessageId = posts.postKey
So complete:
func(){
let vc = storyboard?.instantiateViewControllerWithIdentifier("messagesViewController") as! MessagesViewController
let posts = self.postList[indexPath.row]
//this is the var that i want to past
vc.previousViewMessageId = posts.postKey
navigationController?.pushViewController(vc, animated: false)
}
PS. While not part of the question, I feel I should still mention... Use of the word self should be left to necessity only. In other words, don't use it when it isn't needed. for example self.postList[indexPath.row] :)
https://github.com/raywenderlich/swift-style-guide#use-of-self

Burger menu does not load when opening viewcontroller from push

I have an app which currently uses push notifications and we have started trying to open specific pages of the app from JSON pushes.
This is the code for one of possible pages to open:
//Extract the notification data
if let notificationPayload = launchOptions?[UIApplicationLaunchOptionsRemoteNotificationKey] as? NSDictionary {
// Get which page to open
let viewload = notificationPayload["view"] as? NSString
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
//Load correct view
if viewload == "videos" {
let mainStoryboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let initialViewController : UIViewController = mainStoryboard.instantiateViewControllerWithIdentifier("Videos") as! UIViewController
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
self.window?.rootViewController = initialViewController
self.window?.makeKeyAndVisible()
}
}
The problem is that doing this skips the viewcontroller that allows the burger menu to be opened at the side.
Is there a way to open the burger menu controller and load the correct view from the push?
If you need more information let me know, I'll post updates as needed
You generally shouldn't be creating a new window and setting the root view controller. At least not if you don't make the root view controller the true root VC for your app and ask it to display your specific content from the push.
Generally your root VC should understand that there may be a need to show a particular VC (from a push or somewhere else) and offer the app delegate a way to do that. That may be achieved by forwarding the request until some VC can handle it, it may be simply pushing it onto a navigation controller, it may be posting a notification, or it may be presenting a modal.
There are many potential options, you need to decide which is correct for your app, but the important part is that it ties in with your existing view hierarchy rather than replacing it.