Self.revealViewController() returns nil - swift

I am currently trying to get the pan gesture to reveal the controller. As of right now, my open button works, but when I add the last line, my program crashes because revealViewController is nil. Link to pod: https://github.com/John-Lluch/SWRevealViewController.
import Foundation
import UIKit
class MainViewController : UIViewController{
#IBOutlet weak var mainButton: UIView!
#IBOutlet weak var Open: UIBarButtonItem!
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated);
mainButton.makeCircle();
Open.target = self.revealViewController()
Open.action = #selector(SWRevealViewController.revealToggle(_:));
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer());
}
}

It's likely you haven't set your SWRevealViewController to be the rootViewController. Remember to set Custom Class and Storyboard ID to be SWRevealViewController in your Identity inspector.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let rootVC = storyboard.instantiateViewController(withIdentifier: "SWRevealViewController")
self.view.window?.rootViewController = rootVC
// Cont. with your code...
}
In case you need to show a login page at the beginning, you need a function in you AppDelegate, which allows the window to update the rootViewController
func changeRootVCToSWRevealVC () {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let rootVC = storyboard.instantiateViewController(withIdentifier: "SWRevealViewController")
if let window = self.window{
window.rootViewController = rootVC
}
}
After user logged in, you can change the rooViewController to SWRevealViewController.
if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
appDelegate.changeRootVCToSWRevealVC()
}
If you have a variable storing the state of the last log-in, and want to navigate directly to the Navigation Drawer menu rather than LoginViewController.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
let rootVCId = isLoggedin ? "SWRevealViewController" : "LoginViewController"
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let rootVC = storyboard.instantiateViewController(withIdentifier: rootVCId)
self.view.window?.rootViewController = rootVC
// Cont. with your code...
}

I was just having this same issue and came across this post. My issue turned out to be more of an "oops!" as I missed something obvious and spent 30 minutes scratching my head on it. :facepalm:
If the accepted answer doesn't work for you, check to make sure you connected your menu property to the storyboard with an outlet.
Swift:
#IBOutlet weak var menuButton:UIBarButtonItem!
override func viewDidLoad() {
if (self.revealViewController() != nil) {
menuButton.target = self.revealViewController()
menuButton.action = #selector(SWRevealViewController.revealToggle(_:))
}
}

Related

Appdelegate sigabrt not appearing anything ! in main storyboard

I am making a newsfeed and when I try to add a post it appears this alert[SIGABRT]and not go to the next viewController to write the post here it's a picture , any idea?
and those are some ss from the breakpoint and exception.
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
let authListener = Auth.auth().addStateDidChangeListener { auth, user in
let storyboard = UIStoryboard(name: "Main", bundle: nil )
if user != nil {
UserService.observeUserProfile(user!.uid) { UserProfile in
UserService.currentUserProfile = UserProfile
}
//
let controller = storyboard.instantiateViewController(withIdentifier: "MainTabBarController") as! UITabBarController
self.window?.rootViewController = controller
self.window?.makeKeyAndVisible()
} else {
UserService.currentUserProfile = nil
let controller = storyboard.instantiateViewController(withIdentifier: "MenuViewController") as! ViewController
self.window?.rootViewController = controller
self.window?.makeKeyAndVisible()
}
}
return true
}
}

AppDelegate not showing Storyboard buttons

I am setting up a MainViewController holding multiple ViewControllers the following way:
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
let pageController = UIPageViewController(
transitionStyle: UIPageViewControllerTransitionStyle.scroll,
navigationOrientation: UIPageViewControllerNavigationOrientation.horizontal,
options: nil
)
let navigationController = MainViewController(rootViewController: pageController)
navigationController.view.backgroundColor = UIColor.white
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let leftView = storyboard.instantiateViewController(withIdentifier: "VC1")
let middleView = storyboard.instantiateViewController(withIdentifier: "VC2")
let rightView = storyboard.instantiateViewController(withIdentifier: "VC3")
navigationController.viewControllerArray = [leftView, middleView, rightView]
self.window!.rootViewController = navigationController
self.window!.makeKeyAndVisible()
return true
}
}
My MainViewController also has what is supposed to be a floating button. I have aded this in the storyboard (see picture below). The problem is that the button is not showing. How do i make it show?
I know that somehow this problem is related to the fact that I adding MainViewController in the AppDelegate, but I am not sure how that is hiding the buttons.
You aren't creating your MainViewController instance from the storyboard, you are just creating it with a call to its initialiser. This means that none of your storyboard elements will be loaded
You need something like:
let navigationController = storyboard.instantiateViewController(withIdentifier: "Main")
navigationController.viewControllers = [pageController]

Swift, Firebase - Present different ViewControllers in AppDelegate if User is Logged-in

I'm using Firebase for my app and I want to present different view controllers in AppDelegate with the code below but I keep getting an error.
import UIKit
import Firebase
import FirebaseAuth
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
window = UIWindow()
if Auth.auth().currentUser != nil {
window?.rootViewController = HomeController()
} else {
window?.rootViewController = LoginController()
}
return true
}
...
This is the error.
libc++abi.dylib: terminating with uncaught exception of type
NSException
(lldb)
How can I fix this problem?
Swift 4.0
You can use this function as like below in AppDelegate.
func configureWindowAndMakeVisible(rootVC: UIViewController) {
if let app = UIApplication.shared.delegate as? AppDelegate, let window = app.window {
window.rootViewController = rootVC
window.makeKeyAndVisible()
}
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
if Auth.auth().currentUser != nil {
// Use initialization (i.e HomeController()) only if you had initialize view in Controller
configureWindowAndMakeVisible(rootVC: HomeController())
} else {
configureWindowAndMakeVisible(rootVC: LoginController())
}
return true
}
First of all, you need to know that you need a reference to the already created instance instead of creating a new one. There can be two case
Case 1. If you want to change the initial view controller on the check of if Auth.auth().currentUser == nil or iAuth.auth().currentUser != nil then you can simply write the code in didFinishLaunchingWithOptions in AppDelegate and make sure you must give the identifier in storyboard and use the same identifier in the code
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
let mainView = UIStoryboard(name: "MainStoryboard", bundle: nil)
if Auth.auth().currentUser != nil {
let viewcontroller : MainViewController = mainView.instantiateViewController(withIdentifier: "MainViewIdentifier") as! MainViewController
self.window!.rootViewController = viewcontroller
self.window?.makeKeyAndVisible();
} else {
let viewcontroller : LoginViewController = mainView.instantiateViewController(withIdentifier: "loginViewIdentifier") as! LoginViewController
self.window!.rootViewController = viewcontroller
self.window?.makeKeyAndVisible();
}
return true
}
Case 2. Suppose you have Main/Home/Dash VC (View controller) and it’s always is the initial view controller then there you have implemented the check if Auth.auth().currentUser == nil then present/push the Login view controller else not.
You are Direct Creating New Instance of ViewController
Try the following code
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
if Auth.auth().currentUser != nil {
var mainView: UIStoryboard!
mainView = UIStoryboard(name: "MainStoryboard", bundle: nil)
let viewcontroller : HomeController = mainView.instantiateViewController(withIdentifier: "someViewController") as! HomeController
self.window!.rootViewController = viewcontroller
self.window?.makeKeyAndVisible();
} else {
var mainView: UIStoryboard!
mainView = UIStoryboard(name: "MainStoryboard", bundle: nil)
let viewcontroller : LoginController = mainView.instantiateViewController(withIdentifier: "loginVCIdentifier") as! LoginController
self.window!.rootViewController = viewcontroller
self.window?.makeKeyAndVisible();
}
return true
}
Make Sure you have given identifier to controller from storyboard

When the user is already authenticated, it displays the LoginViewController about half a second before going to the MainController

I'm new to the swift world and I'm developing my application using Firebase features.
I followed the procedures in the Firebase documentation and managed to implement the Authentication Controllers normally, except for one detail that I find strange. When the user is already authenticated, it displays the LoginViewController about half a second before going to the MainController. Is that correct?
I would like the app to go directly to the MainController if the user is already logged in. Thank you.
Follow the code:
class LoginViewController: UIViewController {
#IBOutlet weak var textFieldPassword: UITextField!
#IBOutlet weak var textFieldEmail: UITextField!
var authStateListener: AuthStateDidChangeListenerHandle?
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
authStateListener = Auth.auth().addStateDidChangeListener { (auth, user) in
if user != nil {
self.callMainController()
}
}
}
func callMainController() {
if let storyboard = self.storyboard {
let viewController = storyboard.instantiateViewController(withIdentifier: "MainController") as! UITabBarController
self.present(viewController, animated: true, completion: nil)
} else {
Alert(controller: self).show(message: "Error on show MainController")
}
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
Auth.auth().removeStateDidChangeListener(authStateListener!)
}
#IBAction func didTapLogin(_ sender: Any) {
if let email = self.textFieldEmail.text, let password = self.textFieldPassword.text {
Auth.auth().signIn(withEmail: email, password: password) { (user, error) in
if let error = error {
print(error.localizedDescription)
return
}
print("User Logged")
}
}
}
You should check the login status in AppDelegate and set rootViewController in didFinishLaunchingWithOptions function
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
var initialViewController: UIViewController!
if Auth.auth().currentUser == nil {
initialViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "MainViewController")//replace your mainviewcontroller identifier
} else {
initialViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "LoginViewController")//replace your loginviewcontroller identifier
}
window?.rootViewController = initialViewController
window?.makeKeyAndVisible()
return true
}
I got it that way. Thanks a lot for the help.
var initialViewController: UIViewController!
let storyboard = UIStoryboard(name: "Main", bundle: nil)
if Auth.auth().currentUser == nil {
initialViewController = storyboard.instantiateViewController(withIdentifier: "LoginViewController")
} else {
initialViewController = storyboard.instantiateViewController(withIdentifier: "MainViewController")
}
self.window?.rootViewController = initialViewController
self.window?.makeKeyAndVisible()

how to create very first view for Swift 3

Hi I have made a ViewController.
But I don't know how to add very first view right after an app is tapped.
I added below codes in ViewController.swift
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let controller = storyboard.instantiateViewController(withIdentifier: "FirstViewController")
self.present(controller, animated: true, completion: nil)
the FirstViewController appears after the app tapped and shows white background for about a second.
When you first launch your app, the LaunchScreen.storyboard is displayed, as a transition while your app is loading. You can customise this in Interface Builder.
check the option 'is initial view Controller' for that firstViewController from the storyboard.
You can set initial view controller programmatically or via storyboard
Method 1:programmatically--
Set storyboard-identifire for Viewcontroller in Main.storyboard file
like
After that set rootviewController in Appdelegate class.
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
let mainStoryBoard = UIStoryboard(name: "Main", bundle: nil)
let redViewController = mainStoryBoard.instantiateViewController(withIdentifier: "ViewController") as! ViewController
window?.rootViewController = redViewController
window?.makeKeyAndVisible()
return true
}
}
For setting up with navigation controller use UINavigationController -
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
let mainStoryBoard = UIStoryboard(name: "Main", bundle: nil)
let viewController = mainStoryBoard.instantiateViewController(withIdentifier: "viewController") as! viewController
let navigationController = UINavigationController(rootViewController: viewController)
window?.rootViewController = navigationController
window?.makeKeyAndVisible()
return true
}
Method 2:Via storyboard--
Go to respective storyboard & select Is Initial View Controller