error instantiating a viewcontrolelr modally via code - swift

why with this code, outlets in second view controller are unwrapped as the were nil crashing the app? they even are not appearing. issue happens if I try to access the outlets, but not if I change the view's background.
in view controller 1 button:
let vc = SecondViewController.self.createAcertainCustomAppearenceOfVC()
vc.modalPresentationStyle = .overCurrentContext
vc.modalTransitionStyle = .crossDissolve
present(vc, animated: true, completion: nil)
in second view controller
final class func createAcertainCustomAppearenceOfVC() -> SecondViewController {
let VC = SecondViewController()
VC.view.backgroundColor = .systemRed
// VC.tappedSecondOut.setTitle("push", for: .normal)
VC.tappedSecondOut.backgroundColor = .black
return VC
}

You're trying to instantiate a view controller that has outlets in a storyboard, you need to instantiate the controller from both the storyboard name and the view controller's identifier that is set in Interface Builder.
final class func createAcertainCustomAppearenceOfVC() -> SecondViewController? {
let storyboard = UIStoryboard.init(name: "Main", bundle: nil)
return storyboard.instantiateViewController(withIdentifier: "secondViewControllerIdentifier") as? SecondViewController
}

Related

How can i present programmatically made ViewController on button click

I have this custom UIViewController. It is not connected to anything storyBoard and want to present on clicking a button
class SeeListsViewController: UIViewController {
var tableView = UITableView()
override func viewDidLoad() {
super.viewDidLoad()
self.setUpTableView()
view.addSubview(tableView)
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
// Do any additional setup after loading the view.
}
}
How can i do that. I know the storyBoard way but this one has no identifier and it is all programmatically made
The solution below if you have SeeListsViewController in the storyboard and make sure the storyboard identifier is also SeeListsViewController:
let storyboard = UIStoryboard(name: "<Your storyboard name>", bundle: nil)
let listVC = storyboard.instantiateViewController(withIdentifier: SeeListsViewController.self)
self.present(listVC, animated: true)
A programmatic way to present if you don't have a view controller in the storyboard and all the UI components should be designed programmatically in your viewcontroller
let navVC = UINavigationController(rootViewController: SeeListsViewController())
navVC.modalPresentationStyle = .fullScreen
self.present(navVC, animated: true, completion: nil)

How can i return to Main.storyboard which contains a TabBarController from another Storyboard

I have two storyboards, one which contains everything the app really is, and another which contains an "onboarding"/tutorial to my app.
Once the tutorial is done, I want to navigate back to my original view controller.
This is my code to navigate to the other storyboard:
let defaults = UserDefaults.standard
if defaults.bool(forKey: "firstOpened") {
print("First VC launched")
}else{
var vc: UIViewController
let goTo = UIStoryboard(name: "Onboarding", bundle: nil).instantiateViewController(withIdentifier: "notificationStoryboard") as! FirstOnboardingViewController
self.present(goTo, animated: true, completion: nil)
}
With this, it works, except the TabBarController is not showing, and not working the way I want it to.
And this is my code to navigate back to the Main.Storyboard:
#objc func handleSecondPush() {
//registerForRemoteNotifications()
UserDefaults.standard.set(true, forKey: "firstOpened")
let goTo = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "pushToFeedVC")
self.present(goTo, animated: true, completion: nil)
//self.performSegue(withIdentifier: "goToLink", sender: nil)
}
I have also tried this in the other Storyboard, but with this the button doesn't change the view:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let controller = storyboard.instantiateViewController(withIdentifier: "MainTabBarController") as! UITabBarController
print(controller)
self.window?.rootViewController = controller
self.window?.makeKeyAndVisible()
if let tabBarVc = self.window?.rootViewController as? UITabBarController {
tabBarVc.selectedIndex = 1
}
Question in short terms: So my question is, how can I navigate back to the main.storyboard which will contain the TabBarController with a selected index of 1, from a storyboard that doesn't contain navigation controller or a TabBarController?
When you present the onbaording you should return back to the tab with with
self.dismiss(animated:true,completion:nil)
for complex presentations you can do this for easy re-back
let vc = storyboard.instantiateViewController(withIdentifier: "MainTabBarController") as! UITabBarController
(UIApplication.shared.delegate as! AppDelegate).window!.rootViewController = vc
What is better is to
let goTo = UIStoryboard(name: "Onboarding", bundle: nil).instantiateViewController(withIdentifier: "notificationStoryboard") as! FirstOnboardingViewController
let nav = UINavigationController(rootViewController:goTo)
nav.isNavigationBarHidden = true
self.present(nav, animated: true, completion: nil)
the flow inside the onbarding should be with pushViewController
then to dismiss in the last onbaording vc
if let tab = (UIApplication.shared.delegate as! AppDelegate).window?.rootViewController as? UITabBarController {
tab.dismiss(animated:true,completion:nil)
}

Present ViewController from UNUserNotificationCenterDelegate

In my UNUserNotificationCenterDelegate method I want to jump the user to a specific view controller. I can easily get the VC itself from the storyboard:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "beach")
What I'm not entirely sure of though is now how to actually present it, since I don't have an object handy to call presentViewController on.
If your root is navigationVC
if let nav = self.window?.rootViewController as? UINavigationController {
nav.pushViewController(vc, animated: true)
}

Push navigation from xib Files to storyboard viewcontroller in swift3 [duplicate]

I have a view in my xib file which contain buttons. i want to move to a ViewController when i will press the button (#IBAction). I have used below code
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let nextViewController = storyBoard.instantiateViewControllerWithIdentifier("About") as! AboutViewController
self.presentViewController(nextViewController, animated: true, completion: nil)
I am getting the error "Value of type 'SlideMenuView' has no member 'presentViewController'.
because my class is a UIView type :
class SlideMenuView: UIView {
}
so how can I navigate to other view controller.
That is beacuase the class you are trying to present from is a UIView and not a UIViewController. It has no Present method.
I'm guessing your view (SlideMenuView) is embedded inside a viewcontroller. what you need to do is implement a delegate, and inform your containing viewController to present next Viewcontroller.
code below:
#protocol SlideMenuViewDelegate: class {
func slideMenuViewAboutButtonClicked(menuView: SlideMenuView)
class SlideMenuView: UIView {
weak var delegate: SlideMenuViewDelegate?
#IBAction func aboutButtonClicked(sender: AnyObject) {
self.delegate?.slideMenuViewAboutButtonClicked(self)
}
now, in your viewController, implement this delegate method:
func slideMenuViewAboutButtonClicked(menuView: SlideMenuView) {
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let nextViewController = storyBoard.instantiateViewControllerWithIdentifier("About") as! AboutViewController
self.presentViewController(nextViewController, animated: true, completion: nil)
}
Also, dont forget to assign the sliderMenuView object the viewcontroller as a delegate.
something like:
self.sliderMenuView.delegate = self // (self == the containing viewController
I did it in a different way. In class file
class SlideMenuView: UIView {
var navigationController: UINavigationController? // Declare a navigation controller variable
// And create a method which take a navigation controller
func prepareScreen(navController: UINavigationController)-> UIView {
navigationController = navController
let nibView = NSBundle.mainBundle().loadNibNamed("SlideMenuView", owner: self, options: nil)[0] as! UIView
self.addSubview(nibView)
return nibView
}
// In Button action
#IBAction func btnAction(sender: UIButton) {
var storyBoard = UIStoryboard(name: "Main", bundle: nil)
let nextViewController = storyBoard!.instantiateViewControllerWithIdentifier("NextViewController") as! UIViewController
navigationController?.pushViewController(nextViewController, animated: true)
}
}
// For calling from UIViewController
slideBarMenuIstance.prepareScreen(self.navigationController!)

How to correctly display a tab controller in swift

I'm making a login screen for my app and everything works as intented until I try to present my main view after the login(which uses a Tab Bar Controller).
The only problem is that it displays just the first item on the tab bar. I have to press the other buttons for the to appear.
Im using this code:
//after login...
var storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
var vc: TabBarViewController = storyboard.instantiateViewControllerWithIdentifier("MainController") as! TabBarViewController
self.presentViewController(vc, animated: true, completion: nil)
My guess is that I need to load them all at the same time, but I dont know...
This is how I did it recently. I loaded my tabBarController and the login screen together, once the user has logged in (or completed the first screen experience) you can modally dismiss the controller.
func showloginView() {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let loginViewController: LoginTableViewController = storyboard.instantiateViewControllerWithIdentifier("LoginTVC") as! LoginTableViewController
self.window?.makeKeyAndVisible()
var viewController = storyboard.instantiateViewControllerWithIdentifier("LoginTVC") as! LoginTableViewController
let nav = UINavigationController(rootViewController: viewController)
self.window?.rootViewController?.presentViewController(nav, animated: true, completion: nil)
}
for displaying your tabBarController and editing of any of the tabBarItems
let tabBarController = self.window?.rootViewController as? UITabBarController
let tabBarRootViewControllers: Array = tabBarController!.viewControllers!
let nav = tabBarRootViewControllers[0] as? UINavigationController
Hope this helps =)
If you link an UIButton, you can open a UITabBarController using this (providing you're using a Storyboard)
#IBAction func openTabBar(sender: AnyObject) {
var tabBarController = self.storyboard?.instantiateViewControllerWithIdentifier("tabBarController") as! UITabBarController
self.presentViewController(tabBarController, animated: false, completion: nil)
}
That'll pop the current view and open the tab bar controller.