UINavigationController how to set title and etc in children views - ios

My app structure:
firstView: UIViewController with UINavigationController -- secondView UITabBarController with several UIViewControllers
start app, firstView:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
let vc = ViewController()
let navContr = UINavigationController(rootViewController: vc)
self.window? = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = navContr
self.window?.makeKeyAndVisible()
return true
}
In firtView I click button to open secondView:
let vc = MyTabController() // my UITabBarController
self.navigationController?.pushViewController(vc, animated: true)
start secondView:
class MyTabController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
let gen = MyViewController()
let tabGen = UITabBarItem()
gen.tabBarItem = tabGen
tabGen.image = UIImage(named: "general")
tabGen.title = "Все вопросы"
viewControllers = [gen]
....
}
In my secondView I want set Title, set UISearchControlleer in every tab. But if I write in ViewController
navigationItem.title = "myTitle" nothing changes. I see button "Back" only.
Here's the screenshot

Set title like this in viewDidLoad() Method
self.title = "Your Title"

Related

Making a UITabBarController and UINavigationController Programmatically Swift 4

I am trying to make a UITabBarController and a UINavigationController programmatically. I've tried many tutorials but most use Swift 3 which is too outdated and doesn't work.
AppDelegate.swift Snippet:
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
window = UIWindow(frame: UIScreen.main.bounds)
let journalVC = JournalTableViewController()
let navController = UINavigationController(rootViewController: journalVC)
window?.rootViewController = navController
window?.makeKeyAndVisible()
return true
}
JournalTableViewController.swift Snippet:
var tabBarCnt = UITabBarController()
override func viewDidLoad() {
super.viewDidLoad()
tabBarCnt = UITabBarController()
tabBarCnt.tabBar.barStyle = .black
let journalVC = JournalTableViewController()
journalVC.tabBarItem = UITabBarItem(tabBarSystemItem: .favorites, tag: 0)
tabBarCnt.viewControllers = [journalVC]
self.view.addSubview(tabBarCnt.view)
}
What works:
The build loads onto the simulator
What doesn't work:
The build crashes once loading onto the simulator
After crashing, the error Thread 1: EXC_BAD_ACCESS (code=2, address=0x7ffee6c2ada8) apears over this line 12 of JournalTableViewController.swift Snippet
If you are going to combine a UITabBarController and a UINavigationController then you will want the tab bar controller to be the root view controller. Each tab can have its own navigation controller if required.
If you make the navigation controller the root, then as soon as you push a new view controller, the tab bar will disappear. By making the tab bar the root, you can have a series of navigation hierarchies and switch quickly between them using the tab buttons.
AppDelegate.swift
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
window = UIWindow(frame: UIScreen.main.bounds)
let journalVC = JournalViewController()
let navController = UINavigationController(rootViewController: journalVC)
let tabBarController = UITabBarController()
navController.tabBarItem = UITabBarItem(tabBarSystemItem: .favorites, tag: 0)
tabBarController.viewControllers = [navController]
window?.rootViewController = tabBarController
window?.makeKeyAndVisible()
return true
}
There is no need for any specific code in your view controller class.
JournalTableViewController.swift Snippet:
override func viewDidLoad() {
super.viewDidLoad()
}
I think there is a typo in your snippet. In the following code, we added an intermediate vc to solve recursive problems.
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
window = UIWindow(frame: UIScreen.main.bounds)
let journalVC = JournalViewController()
let navController = UINavigationController(rootViewController: journalVC)
window?.rootViewController = navController
window?.makeKeyAndVisible()
return true
}
Here is journal vc:
class JournalViewController: UIViewController{
var tabBarCnt = UITabBarController()
override func viewDidLoad() {
super.viewDidLoad()
tabBarCnt = UITabBarController()
tabBarCnt.tabBar.barStyle = .black
let journalVC = JournalTableViewController()
journalVC.tabBarItem = UITabBarItem(tabBarSystemItem: .favorites, tag: 0)
tabBarCnt.viewControllers = [journalVC]
self.view.addSubview(tabBarCnt.view)
}
}
while the tableviewcontroller should be like this:
class JournalTableViewController: UITableViewController{
}

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 switch between uiViews from a non UIView class

So here's the situation. I have an app which presents a tabBarController as its root view controller, with a number of tabItems. So here's the setup in my app delegate
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let vc1 = VC1(nibName: "VC1", bundle: nil)
let vc2 = VC2(nibName: "VC2", bundle: nil)
let menuTabBarController = MenuTabBarController(nibName: "MenuTabBarController", bundle: nil)
menuTabBarController.viewControllers = [VC1,VC2]
window = UIWindow(frame: UIScreen.mainScreen().bounds)
window?.rootViewController = menuTabBarController
window?.makeKeyAndVisible()
//Setup tab bar
UITabBar.appearance().barTintColor = UIColor.blackColor()
let IMG1 = UIImage(named: "img2.png")
let IMG2 = UIImage(named: "img2.png")
VC1.tabBarItem = UITabBarItem(
title: "View 1",
image: IMG1,
tag: 1)
VC2.tabBarItem = UITabBarItem(
title: "View 2",
image: IMG2,
tag:2)
return true
}
func applicationWillResignActive(application: UIApplication) {
}
func applicationDidEnterBackground(application: UIApplication) {
}
}
So notice I have two UIViewController classes(VC1 and VC2) nested within the menuTabBar. Now from menuTabBar class, I can easily switch between the views like so
class MenuTabBarController: UITabBarController,UITabBarControllerDelegate{
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self//Set tabbarcontroller delegate
}
// UITabBarControllerDelegate
func tabBarController(tabBarController: UITabBarController, didSelectViewController viewController: UIViewController) {
tabBarController.selectedIndex = 1;//Say I wanted to transition to VC2
}
}
But What I ultimately want to do is to be able to switch between the two UIViewControllers from another class that is not a UIViewController. I attempted something like this
class Actions(){
func someFunctionThatSwitchesToVC2(){
//So I create a reference to appDelegate which in turn, is supposed to reference the tab bar and switch between its child views
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let tabBarController: UITabBarController = (appDelegate.window?.rootViewController as? UITabBarController)!
tabBarController.selectedIndex = 1
}
}
When I run the someFucntionThatSwitchesToVC2, I get this error "fatal error: Index out of range". Obviously I'm not doing something right. Any ideas greatly appreciated
PS, When I do tabBarController.selectedIndex = 0, I don't get the error but nothing happen
I think you are doing typo while assigning ViewControllers. Change this line:
menuTabBarController.viewControllers = [VC1,VC2]
with below line:
menuTabBarController.viewControllers = [vc1,vc2]

Swift – Instantiating a navigation controller without storyboards in App Delegate

I'm rebuilding an app without storyboards and the part of it that I'm having the most trouble with is navigating view-to-view programatically. Few things are written out there which don't use storyboards, so finding an answer for this has been tough.
My problem is pretty simple. I have my ViewController and my SecondViewController and I want to push from the former to the latter.
In AppDelegate:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
window = UIWindow(frame: UIScreen.mainScreen().bounds)
window?.backgroundColor = UIColor.whiteColor()
window?.rootViewController = ViewController()
window?.makeKeyAndVisible()
return true
}
Then in ViewController.swift:
class ViewController: UIViewController, AVAudioPlayerDelegate, UITextFieldDelegate {
override func viewDidLoad() {
super.viewDidLoad()
startFinishButton.setTitle("Begin", forState: .Normal)
startFinishButton.addTarget(self, action: "moveToSecondViewController", forControlEvents: .TouchUpInside)
view.addSubview <*> startFinishButton
}
func moveToSecondViewController(sender: UIButton) {
let vc = SecondViewController()
println(self.navigationController) // returns nil
self.navigationController?.pushViewController(vc, animated: true)
}
}
Printing self.navigationController returns nil. I've tried doing:
var navController = UINavigationController() when the ViewController class is created (but outside of ViewDidLoad, right under the class declaration) and done the push using the navController var but that hasn't worked.
I'm thinking maybe the solution is to create a navigation controller in App Delegate that the whole app would use, I guess as a global variable?
My hope is that this post can serve many others who are new to Swift and want to remove storyboards from their app.
Thanks for taking a look and for your help.
In Swift 3
Place this code inside didFinishLaunchingWithOptions method in AppDelegate class.
window = UIWindow(frame: UIScreen.main.bounds)
let mainController = MainViewController() as UIViewController
let navigationController = UINavigationController(rootViewController: mainController)
navigationController.navigationBar.isTranslucent = false
self.window?.rootViewController = navigationController
self.window?.makeKeyAndVisible()
In AppDelegate
var window: UIWindow?
var navController: UINavigationController?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
navController = UINavigationController()
var viewController: ViewController = ViewController()
self.navController!.pushViewController(viewController, animated: false)
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
self.window!.rootViewController = navController
self.window!.backgroundColor = UIColor.whiteColor()
self.window!.makeKeyAndVisible()
return true
}
In ViewController
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.title = "FirstVC"
var startFinishButton = UIButton.buttonWithType(UIButtonType.System) as! UIButton
startFinishButton.frame = CGRectMake(100, 100, 100, 50)
startFinishButton.backgroundColor = UIColor.greenColor()
startFinishButton.setTitle("Test Button", forState: UIControlState.Normal)
startFinishButton.addTarget(self, action: "buttonAction:", forControlEvents: UIControlEvents.TouchUpInside)
self.view.addSubview(startFinishButton)
}
func buttonAction(sender:UIButton!)
{
println("Button tapped")
let vc = SecondViewController()
self.navigationController?.pushViewController(vc, animated: true)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
In Swift 5 and Xcode 13 there is a SceneDelegate along with the AppDelegate. So now to completely remove the storyboard from a project and embed the view controller in a navigation controller do the following:
Delete the actual storyboard in the Project Navigator
Select the project in the Project Navigator, select Target and then the General tab, then delete the storyboard from Main Interface
In the info.plist file delete the storyboard from:
Application Scene Manifest > Scene Configuration > Application Session Role > Item 0 (Default Configuration) > Storyboard Name
Then in the scene delegate change the scene function to look like this:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
let window = UIWindow(windowScene: windowScene)
let navigationController = UINavigationController(rootViewController: YourViewController())
window.rootViewController = navigationController
self.window = window
window.makeKeyAndVisible()
}

Moving from one UIViewController to another in Swift programmatically

I have 2 ViewControllers. I don't have a storyboard. I want to move from the first view to another once everything is done in first viewController. What is the way to do it? It is something like this, the first view shows an image and in the background makes some API calls. After API call succeeds, I want it to move to the second ViewController(LoginActivityViewController). I tried calling this in the first ViewController:
var loginActivity = LoginActivityViewController()
self.navigationController.pushViewController(loginActivity, animated: true)
But, this did not work. How to do this?
Here is my application function in AppDelegate
func application(application: UIApplication!, didFinishLaunchingWithOptions launchOptions: NSDictionary!) -> Bool {
// Override point for customization after application launch.
window = UIWindow(frame: UIScreen.mainScreen().bounds)
let navigationController: UINavigationController = UINavigationController(rootViewController: RootViewController())
navigationController.setNavigationBarHidden(true, animated: false)
window!.rootViewController = navigationController
window!.makeKeyAndVisible()
return true
}
Here is my RootViewController's viewDidLoad()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let image1 = UIImage(named: "Default.png")
let imageview = UIImageView(image: image1)
self.view.addSubview(imageview)
var loginActivity = LoginActivityViewController()
self.navigationController.pushViewController(loginActivity, animated: true)
}
this how your method should look with initing a navigation controller properly:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {
window = UIWindow(frame: UIScreen.mainScreen().bounds)
let rootViewController: RootViewController = RootViewController(nibName: "RootViewController", bundle: nil)
let navigationController: UINavigationController = UINavigationController(rootViewController: rootViewController)
window!.rootViewController = navigationController
window!.makeKeyAndVisible()
return true
}
and now you are able to push new view controllers into the hierarchy.
update
if you don't want to show the navigation bar insert this line into the code above.
navigationController.setNavigationBarHidden(true, animated: false)
var next = self.storyboard?.instantiateViewControllerWithIdentifier("DashboardController") as! DashboardController
self.presentViewController(next, animated: true, completion: nil)
don't forget to set ViewController StoryBoard Id in StoryBoard -> identity inspector

Resources