SplitViewController not work (Swift) - ios

I'm trying to make an application that supports SplitViewController.
But my application crashes on startup.
How can I fix this?
MenuViewController --> ViewController --> DetailViewController
AppDelegate.swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
if UIDevice.current.userInterfaceIdiom == .pad {
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window!.backgroundColor = UIColor.white
let splitViewController = UISplitViewController()
let menuViewController = MenuViewController()
let homeViewController = ViewController()
let secondViewController = DetailViewController()
let menuNavigationController = UINavigationController(rootViewController:menuViewController)
let homeNavigationController = UINavigationController(rootViewController:homeViewController)
let secondNavigationController = UINavigationController(rootViewController:secondViewController)
splitViewController.viewControllers = [menuNavigationController,homeNavigationController,secondNavigationController]
self.window!.rootViewController = splitViewController
self.window!.makeKeyAndVisible()
return true
} else {
}
return true
}
Error: (Example) - MenuViewController
override func viewDidLoad() {
super.viewDidLoad()
let isDarkMode = UserDefaults.standard.bool(forKey: "isDarkMode")
if isDarkMode == true {
self.tableView.backgroundColor = UIColor(red: 37/255, green: 38/255, blue: 39/255, alpha: 1)
} else {
self.tableView.backgroundColor = UIColor(red: 245/255, green: 245/255, blue: 245/255, alpha: 1)
}
tableView.tableFooterView = UIView(frame: CGRect.zero)
My StoryBoard:

Your problem is that you design your view controllers with storyboards, but you create them in code while effectively circumventing storyboards. That particular error happens because it was the responsibility of the storyboards to create the tableView, but now since you circumvented storyboards it is nil.
You have two options:
create the splitViewController in storyboards and use it as initial view controller of the app (and drop the programmatic creation of the splitViewController in appDelegate).
Get those view controllers from the storyboards, e.g.:
let menuViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "menuController")
In this I assume that the storyboard name is "Main", and that you set the storyboard identifier of the MenuViewController is set to "menuController" - be careful, viewController's class (MenuViewController) is not the same thing as viewController's storyboard identifier (in my case I used '"menuController"'):
Do the same thing for all those view controllers that you created in storyboards.

Related

Get custom NavigationController class from custom UIViewController

I am trying to implement the side navigation menu (one that we have in Android) in iOS App.So far i tried the following:-
AppDelegate.swift :-
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var bridge: RCTBridge!
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions:
[UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let sb = UIStoryboard(name: "mystoryboard", bundle: Bundle.main)
let rootViewController: UIViewController =
sb.instantiateViewController(withIdentifier:
"NativeLabelSwiftViewController") as UIViewController
let navigationController = UINavigationController(rootViewController:
rootViewController)
window = UIWindow(frame: UIScreen.main.bounds)
window!.rootViewController = navigationController
window!.makeKeyAndVisible()
return true
}
The above is my AppDelegate class since it is a React Native project we have the generated code as well.Here added the following code to instantiate my rootViewClass(NativeLabelSwift) by following code :-
let sb = UIStoryboard(name: "mystoryboard", bundle: Bundle.main)
let rootViewController: UIViewController =
sb.instantiateViewController(withIdentifier:
"NativeLabelSwiftViewController") as UIViewController
NavigationLabelSwiftViewController.swift(Custom View Class) :-
class NativeLabelSwiftViewController: UIViewController{
var bridge: RCTBridge!
override func viewDidLoad() {
super.viewDidLoad()
title = "Production Tracking"
let btn2 = UIButton(type: .custom)
btn2.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
btn2.addTarget(self,
action:#selector(NativeLabelSwiftViewController.
onBtn2Clicked.(_:)), for: .touchUpInside)
let item2 = UIBarButtonItem(customView: btn2)
self.navigationItem.setLeftBarButton(item2, animated: true)
}
#IBAction func onBtn2Clicked(_ sender: UIBarButtonItem) {
if let navViewController = self.navigationController as?
NavigationController {
// navigation view controller is available
}
else{
// navigation view controller not available
}
}
}
The Navigation Controller has a UIViewController class (NativeLabelSwiftViewController) that has a button in Tab Bar.On Press of the Button i need to access the Navigation Controller method.But i am not able to get the navigation controller using the below code :-
let navViewController = self.navigationController as?
NavigationController; //this is NIL
But
let uiViewController = self.navigationController as?
UINavigationController; //this is not NIL
You are not referring your custom navigation controller in the AppDelegate. You used UINavigationController(rootViewController: rootViewController).
You if you want to use the storyBoard NavigationController, In AppDelegate use -
let nav = UIStoryboard.init(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "NavigationController") as! NavigationController
window = UIWindow(frame: UIScreen.main.bounds)
window!.rootViewController = nav
window!.makeKeyAndVisible()
return true
Note: Don't forget to put an Identifier for the StoryBoard NavigationController.

Navigation bar appear from black color?

I am setting a new navigation for my app on launch. But when I launch it appears from a black color animation.After black color it sets it navigation bar. Please tell me what is issue.
I am using below code
var controller = UIViewController()
//App Theming
var navController = UINavigationController()
navController.navigationBar.barTintColor = UIColor.white
navController.navigationBar.tintColor = UIColor.white
navController.navigationBar.titleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.white]
navController.navigationBar.shadowImage = UIImage()
navController.navigationBar.setBackgroundImage(UIImage(), for: .default)
navController.navigationBar.isTranslucent = false
navController = UINavigationController(rootViewController: viewcontroller)
navController.navigationBar.isHidden = true
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.window?.rootViewController = navController
appDelegate.window?.makeKeyAndVisible()
The problem is this line:
navController.navigationBar.isHidden = true
Delete it and try again.
Please use snippet bellow
In this I am using ViewController from Main storyboard
// mainStoryboard
let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
// rootViewController
let rootViewController = mainStoryboard.instantiateViewController(withIdentifier: "ViewController") as? ViewController
// navigationController
let navigationController = UINavigationController(rootViewController: rootViewController!)
//App Theming
navigationController.navigationBar.barTintColor = UIColor.white
navigationController.navigationBar.tintColor = UIColor.white
navigationController.navigationBar.titleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.white]
navigationController.title = "Testing Th"
navigationController.navigationBar.shadowImage = UIImage()
navigationController.navigationBar.setBackgroundImage(UIImage(), for: .default)
navigationController.navigationBar.isTranslucent = false
navigationController.navigationBar.isHidden = true
// self.window
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window!.rootViewController = navigationController
self.window!.makeKeyAndVisible()
If I unhide NavigationBar
navigationController.navigationBar.isHidden = false
you can clearly see the results
I can see that you did not give the navigationController any viewControllers.
You need to pass the navigation controller at least one viewController for it to know which viewController to start your
navigation process from, follow the code below:
var window: UIWindow?
let nav = UINavigationController()
1- here is where i declared my Initial viewController (where i want my navigation process to start from)
var main = HomeViewController(nibName: "HomeViewController", bundle: nil)
2- here is where i give the navigationController the first viewController to start from.
window?.rootViewController = nav
nav.viewControllers = [main]//you need to have this line
nav.isNavigationBarHidden = true
window?.makeKeyAndVisible()
alright i just noticed you're using storyboards, give this a try:
var storyboard = UIStoryboard(name: "Main", bundle: nil)
var ivc = storyboard.instantiateViewController(withIdentifier: "ViewController") as? ViewController
navigationController?.pushViewController(anIvc, animated: true)
window.rootViewController = ivc
window.rootViewController = navigationController
window.makeKeyAndVisible()
Your code should be placed in
import UIKit
// AppDelegate class file
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Be attentive. controller allocated withou any layout. Change to custom controller class or load from IB resource (storyboard/nib)
let controller = UIViewController()
let navigationController = rootNavigationController
// Setup viewControllers. Just one controller as root
navigationController.viewControllers = [controller]
// You already have a reference to window in your AppDelegate
window.rootViewController = navigationController
window.makeKeyAndVisible()
}
extension AppDelegate {
// Move out of AppDelegate class code to create theming NavigationController
private var rootNavigationController: UINavigationController {
let navController = UINavigationController()
navController.navigationBar.barTintColor = UIColor.white
navController.navigationBar.tintColor = UIColor.white
navController.navigationBar.titleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.white]
navController.navigationBar.shadowImage = UIImage()
navController.navigationBar.setBackgroundImage(UIImage(), for: .default)
navController.navigationBar.isTranslucent = false
navController.navigationBar.isHidden = true
// If it theme for all application you should use appearances
/* For Example
UINavigationBar.appearance().titleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.white]
UINavigationBar.appearance().tintColor = .white
*/
return navController
}
}
You possible errors:
controller instance haven't any layout. By default ViewController
haven't anything
You code call from separated place. It's market by you call of AppDelegate instance. Configure you rootViewController in
didFinishLoading
You have an separated ViewController that placed as root

How can I embed my navigation controller into my tab bar controller programmatically in Swift Xcode 8.2?

I have been teaching my self how to develop and I got to the point to where I need guidance from experts. I created some of the user interface programmatically using the MVC structure. My question is how can I embed my navigation controller into my tab bar controller so my tab bar controller can be on every screen. I made the tab bar controller in main.storyboard and referenced it in the View controller I named Home Controller.
let storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let tabViewController = storyboard.instantiateViewController(withIdentifier: "TabBar")
self.present(tabViewController, animated: true, completion: nil)
The code above is in the view did load function. I was wondering do I need to change up the root view controller in my app delegates?
window = UIWindow(frame: UIScreen.main.bounds)
window?.makeKeyAndVisible()
let layout = UICollectionViewFlowLayout()
window?.rootViewController = UINavigationController(rootViewController: HomeController(collectionViewLayout: layout))
This is in my finished launched func.
Use following lines
var navigationController = UINavigationController(rootViewController: viewController));
tabBarController.viewControllers = [navigationController,firstViewControllersecondViewController, ]
create a separate UITabBarController class and initialize it in AppDelegate like this:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
window = UIWindow(frame: UIScreen.main.bounds)
window?.rootViewController = MyTabBarController()
window?.makeKeyAndVisible()
return true
}
and the custom tabBarController
import UIKit
class MyTabBarController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
self.tabBar.barTintColor = UIColor.black
self.tabBar.tintColor = UIColor.white
self.tabBar.unselectedItemTintColor = UIColor.white.withAlphaComponent(0.4)
let firstViewController = FirstViewController()
let firstViewTabBarItem = UITabBarItem(title: "First", image: UIImage(named: "calculator"), selectedImage: UIImage(named: "calculator"))
firstViewController.tabBarItem = firstViewTabBarItem
firstViewController.tabBarItem.tag = 0
let historyViewController = HistoricDataViewController()
historyViewController.tabBarItem = UITabBarItem(tabBarSystemItem: .history, tag: 1)
let tabBarList = [calculateViewController, historyViewController]
viewControllers = tabBarList.map{UINavigationController(rootViewController: $0)}
}
}
Hope this example helps.

How to reset navigationviewcontroller ios swift

I am having app with Slider where I have provided drop down to switch between users. As soon as app user switch to other user I want to reset entire navigation flow and start it from 1st screen.
For e.g
Screen A -> Screen B -> Screen C -> Screen D -> User opens slider and switch users -> Jump to Screen A (Remove other screen from navigation). We can consider gmail app example here, where we can switch between different accounts and gmail app redirect user to primary inbox.
EDIT :
I am using library for Slider menu available on git.
https://github.com/dekatotoro/SlideMenuControllerSwift
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var navigationController: UINavigationController?
var storyboard: UIStoryboard?
var leftViewController: LeftSidePanelViewController?
// var uuid: String?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
if Utility.getUserStatus() == 0 {
storyboard = UIStoryboard(name: "Main", bundle: nil)
let mainViewController = storyboard!.instantiateViewControllerWithIdentifier("LoginViewController") as! LoginViewController
leftViewController = storyboard!.instantiateViewControllerWithIdentifier("LeftSidePanelViewController") as? LeftSidePanelViewController
navigationController = UINavigationController(rootViewController: mainViewController)
UINavigationBar.appearance().tintColor = UIColor.whiteColor()
leftViewController!.mainViewController = navigationController
let slideMenuController = ExSlideMenuController(mainViewController:navigationController!, leftMenuViewController: leftViewController!)
slideMenuController.automaticallyAdjustsScrollViewInsets = true
slideMenuController.delegate = mainViewController
self.window?.backgroundColor = UIColor(red: 236.0, green: 238.0, blue: 241.0, alpha: 1.0)
self.window?.rootViewController = slideMenuController
self.window?.makeKeyAndVisible()
Utility.setUUID(UIDevice.currentDevice().identifierForVendor!.UUIDString)
} else {
storyboard = UIStoryboard(name: "Main", bundle: nil)
let mainViewController = storyboard!.instantiateViewControllerWithIdentifier("HomeViewController") as! HomeViewController
leftViewController = storyboard!.instantiateViewControllerWithIdentifier("LeftSidePanelViewController") as? LeftSidePanelViewController
navigationController = UINavigationController(rootViewController: mainViewController)
UINavigationBar.appearance().tintColor = UIColor.whiteColor()
leftViewController!.mainViewController = navigationController
let slideMenuController = ExSlideMenuController(mainViewController:navigationController!, leftMenuViewController: leftViewController!)
slideMenuController.automaticallyAdjustsScrollViewInsets = true
slideMenuController.delegate = mainViewController
self.window?.backgroundColor = UIColor(red: 236.0, green: 238.0, blue: 241.0, alpha: 1.0)
self.window?.rootViewController = slideMenuController
self.window?.makeKeyAndVisible()
}
return true
}
}
I have tried different solutions for this but nothing seems to be working.
var alreadyPushed = false
//Check if the view was already pushed
if let viewControllers = self.navigationController?.viewControllers {
for viewController in viewControllers {
if let viewController = viewController as? HomeViewController {
self.navigationController?.popToViewController(viewController, animated: true);
print(" Push Your Controller")
alreadyPushed = true
break
}
}
}
if alreadyPushed == false {
print("Pushing...")
let YourControllerObject = self.storyboard?.instantiateViewControllerWithIdentifier("HomeViewController") as! HomeViewController
self.navigationController?.presentViewController(YourControllerObject, animated: true, completion: nil)
// HERE also tried pushViewController but that was also not working..
self.navigationController?.dismissViewControllerAnimated(false, completion: nil)
}
Solution 2:-
Also tried self.navigationController?.viewController.removeAll() and then push/present the HomeView but that is also not working.
Anyone having any suggestion or tips to solve this.
A very fast way:
// Put this line in the UIViewController where you want to reset navigation
self.navigationController?.viewControllers = [self]
You will erase the view controller stack and reset the navigation.
You can use for it
self.navigationController?.popToRootViewControllerAnimated(true)
or make some hack with navigation stack
var viewCtonrollers = self.navigationController?.viewControllers
let firstViewCtr = viewCtonrollers?.first;
viewCtonrollers?.removeAll()
viewCtonrollers?.insert(firstViewCtr!, atIndex: 0)
self.navigationController?.viewControllers = viewCtonrollers!
Instead of reverting back the navigation, Why not you can set rootViewController for Window again like below?
SharedAppDelegate.window?.rootViewController = MainStoryboard.instantiateViewControllerWithIdentifier("HomeNavigationController")
For Swift 3, use the following code:
self?.navigationController?.popToRootViewController(animated: true)

Initial view controllers in Swift

I am new programming in Swift but i`m having some problems.
I have a login page (LoginViewController) and when i click the button it heads to another View Controller (MainViewController).
The problem is that in MainViewController i'm using a Slide Menu from here: https://github.com/dekatotoro/SlideMenuControllerSwift
and the code where the slide menu is done is in AppDelegate:
private func createMenuView() {
// create viewController code...
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let mainViewController = storyboard.instantiateViewControllerWithIdentifier("MainViewController") as! MainViewController
let leftViewController = storyboard.instantiateViewControllerWithIdentifier("LeftViewController") as! LeftViewController
let rightViewController = storyboard.instantiateViewControllerWithIdentifier("RightViewController") as! RightViewController
let nvc: UINavigationController = UINavigationController(rootViewController: mainViewController)
UINavigationBar.appearance().tintColor = UIColor(hex: "689F38")
leftViewController.mainViewController = nvc
let slideMenuController = ExSlideMenuController(mainViewController:nvc, leftMenuViewController: leftViewController, rightMenuViewController: rightViewController)
slideMenuController.automaticallyAdjustsScrollViewInsets = true
self.window?.backgroundColor = UIColor(red: 236.0, green: 238.0, blue: 241.0, alpha: 1.0)
self.window?.rootViewController = slideMenuController
self.window?.makeKeyAndVisible()
}
and in this application function the createMenuView is called:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
self.createMenuView()
return true
}
the problem with this is that LoginViewController is the Initial View Controller, and when i leave it like that the MainViewController appears as the Initial View Controller.
How can i do so that the LoginViewController is the initial and when the user press the button in login set to MainViewController with all the menu thing.
Please help me i really don`t know what to do :(
It is because you're replacing root view controller to be slideMenuController in createMenuView method and calling it in didFinishLaunchingWithOptions in app delegate. This code will get executed as soon as the app is launched.
Solution: Instead of doing this, try to get the application delegate instance using UIApplication.sharedApplication().delegate in createMenuView method, define this method in LoginViewController and then call this method after button click in LoginViewController (where ever you wanted to call).
Please call createMenuView() method after button click in login view controller, may be in ViewWillAppear of mainViewController.
Rewrite the method like this inside LoginViewController or where ever you want it to be based on your requirement:
private func createMenuView() {
// create viewController code...
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let mainViewController = storyboard.instantiateViewControllerWithIdentifier("MainViewController") as! MainViewController
let leftViewController = storyboard.instantiateViewControllerWithIdentifier("LeftViewController") as! LeftViewController
let rightViewController = storyboard.instantiateViewControllerWithIdentifier("RightViewController") as! RightViewController
let nvc: UINavigationController = UINavigationController(rootViewController: mainViewController)
UINavigationBar.appearance().tintColor = UIColor(hex: "689F38")
leftViewController.mainViewController = nvc
let slideMenuController = ExSlideMenuController(mainViewController:nvc, leftMenuViewController: leftViewController, rightMenuViewController: rightViewController)
slideMenuController.automaticallyAdjustsScrollViewInsets = true
let appDelegate = UIApplication.sharedApplication().delegate
appDelegate.window?.backgroundColor = UIColor(red: 236.0, green: 238.0, blue: 241.0, alpha: 1.0)
appDelegate.window?.rootViewController = slideMenuController
appDelegate.window?.makeKeyAndVisible()
}
Call this method on the #IBAction of the login button in LoginViewController.
I hope this answers you're question.

Resources