How can i change the tab bar? i know this post seems duplicate but i cant find any exist question that similar to me. Right now my current
selectedIndex = 0
so i want to make it go to tab number 3 which is
selectedIndex = 2
But i also want to send data from currentView to nextView. if i using push+selectedindex it will go to tab 3 but push the view from selectedindex = 0, and there is no data send to selectedIndex = 2
My current code
func redeemBtnPressed(_ sender: UIButton) {
let selectedRedeemBtnInfo = fixedGridInfo[sender.tag] as! Dictionary<String, AnyObject>
sender.showsTouchWhenHighlighted = true
let storyboard = UIStoryboard(name: "FlightExploration", bundle: nil)
let searchFlightVC = storyboard.instantiateViewController(withIdentifier: "SearchFlightVC") as! SearchFlightViewController
var newFlightType = String()
if "\(selectedRedeemBtnInfo["FlightType"]!)" == "Return" {
newFlightType = "Round"
} else {
newFlightType = "One"
}
searchFlightVC.flightType = newFlightType
searchFlightVC.fromHome = true
searchFlightVC.departure = "\(selectedRedeemBtnInfo["Departure"]!) (\(selectedRedeemBtnInfo["DepartureCityCode"]!)"
searchFlightVC.arrival = "\(selectedRedeemBtnInfo["Destination"]!) (\(selectedRedeemBtnInfo["DestinationCityCode"]!)"
self.navigationController?.pushViewController(searchFlightVC, animated: true)
tabBarController?.selectedIndex = 2
}
You can try this to send the data to that UIViewController which is a ViewController of UITabBarController
var yourViewController : TempViewController
if let arrController = tabBarController?.viewControllers {
for vc in arrController {
if vc is TempViewController {
yourViewController = vc as! TempViewController
}
}
}
yourViewController.yourData = dataToPass
tabBarController?.selectedIndex = 2
Modified from Rajat's answer seems helped me to solved the issue
func redeemBtnPressed(_ sender: UIButton) {
let selectedRedeemBtnInfo = fixedGridInfo[sender.tag] as! Dictionary<String, AnyObject>
sender.showsTouchWhenHighlighted = true
var newFlightType = String()
if "\(selectedRedeemBtnInfo["FlightType"]!)" == "Return" {
newFlightType = "Round"
} else {
newFlightType = "One"
}
if let arrController = tabBarController?.viewControllers {
for vc in arrController {
if vc.childViewControllers[0] is SearchFlightViewController {
let displayViewController = vc.childViewControllers[0] as! SearchFlightViewController
let _ = displayViewController.navigationController?.popToRootViewController(animated: true)
//displayViewController.flightType = newFlightType
displayViewController.flightTypeFromHome = newFlightType
displayViewController.fromHome = true
displayViewController.departure = "\(selectedRedeemBtnInfo["Departure"]!) (\(selectedRedeemBtnInfo["DepartureCityCode"]!)"
displayViewController.arrival = "\(selectedRedeemBtnInfo["Destination"]!) (\(selectedRedeemBtnInfo["DestinationCityCode"]!)"
displayViewController.flightType = "Round"
displayViewController.departureDateLbl = "Select One"
displayViewController.passenger = "1 Adult"
displayViewController.adultCount = 1
displayViewController.childCount = Int()
displayViewController.infantCount = Int()
tabBarController?.selectedIndex = 2
tabBarController?.tabBar((tabBarController?.tabBar)!, didSelect: (tabBarController?.tabBar.items?[2])!)
}
}
}
}
Rajat's answer Switch Tab Bar and Pass data, in Swift 4.2, iOS 11 need some changes to be done:
func switchToTab2(){}
var yourViewController = MyTab2ViewController()
if let arrController = self.tabBarController?.viewControllers {
for vc in arrController {
if vc is MyTab2ViewController {
yourViewController = vc as! MyTab2ViewController
yourViewController.productTitle = "Title"
self.tabBarController?.selectedIndex = 1 /// tabs start from 0
}
}
}
}
MyTab2ViewController is your viewcontroller connected to tab bar with index 1. (first tab index: 0)
Related
I'm trying to get the values from 4 different variables in PrefsViewController in ViewController but when PrefsViewController is dismissed the values reset.
Snippet of ViewController.swift
class ViewController: NSViewController, NSWindowDelegate {
var triesEnabled = false
var minNumber = 0
var maxNumber = 20
var maxTries = 3
#objc func applyPrefs() {
let mainSB = NSStoryboard(name: "Main", bundle: nil)
let prefsVC: PrefsViewController = mainSB.instantiateController(withIdentifier: "prefsViewController") as! PrefsViewController
minNumber = prefsVC.prefsMinNum
maxNumber = prefsVC.prefsMaxNum
triesEnabled = prefsVC.prefsTriesEnabled
maxTries = prefsVC.prefsMaxTries
print("\(minNumber) \(maxNumber) \(triesEnabled) \(maxTries)") // here I can see that it has been reset to the default values
resetGame(minRange: minNumber, maxRange: maxNumber, isTriesEnabled: triesEnabled, triesLimit: maxTries)
}
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(applyPrefs), name: Notification.Name("notifyApplyPrefs"), object: nil )
resetGame(minRange: minNumber, maxRange: maxNumber, isTriesEnabled: triesEnabled, triesLimit: maxTries)
}
}
Snippet of PrefsViewController
class PrefsViewController: NSViewController {
var triesOn = false
var prefsMinNum: Int = 0
var prefsMaxNum: Int = 20
var prefsTriesEnabled: Bool = false
var prefsMaxTries: Int = 3
#IBAction func closeButton(_ sender: Any) {
if (!minNumTextField.stringValue.isInt || !maxNumTextField.stringValue.isInt || !triesTextField.stringValue.isInt) {
let alert = NSAlert()
alert.messageText = "Error"
alert.informativeText = "You can only enter (whole) numbers in the text fields."
alert.alertStyle = .warning
alert.addButton(withTitle: "OK")
alert.runModal()
return
}
prefsMinNum = Int(minNumTextField.intValue)
prefsMaxNum = Int(maxNumTextField.intValue)
prefsTriesEnabled = triesOn
prefsMaxTries = Int(minNumTextField.intValue)
print("minNumTextField: \(prefsMinNum) maxNumTextField: \(prefsMaxNum) triesCheckBox: \(prefsTriesEnabled) triesTextField: \(prefsMaxTries)")
NotificationCenter.default.post(name: Notification.Name("notifyApplyPrefs"), object: nil)
self.dismiss(self)
}
}
The prefs view is shown as a sheet (I don't know if that's important)
When you use instantiateController you're creating a new, never before used, instance of the controller. If you want to have the data transferred using a notification, send self as the object when you call post and then use that to get your variables.
You would also need to change applyPrefs so that it takes a Notification parameter so that the notification object is available to you.
Merry Christmas! I am currently making a "reminders" app at the moment. My "secondary" TableViews fail to pass data back into the "main" TableView. (please see image below). I need the data to pass back into the "main" TableView so that I can save it and display that into another TableView, so the user can see the tasks they have put in.
The code inside the IconTableViewController (and ShowTableViewController):
var userImage: String = ""
var userTitle: String = ""
var userDesc: String = ""
var frequency: String = ""
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let navigationViewController = segue.destination as? UINavigationController {
guard let viewController = navigationViewController.topViewController as? NewItemTableViewController else { return }
let userImageNew = userImage
let userTitleOld = userTitle
let userDescOld = userDesc
let frequencyOld = frequency
viewController.selectedImage = userImageNew
viewController.userTitle = userTitleOld
viewController.userDesc = userDescOld
viewController.selectedFrequency = frequencyOld
}
}
The code inside NewItemTableViewController:
var selectedImage: String = ""
var selectedFrequency: String = ""
var userTitle: String = ""
var userDesc: String = ""
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showSelect" {
let userImageOld = selectedImage
let userTitleNew = titleTextField.text
let userDescNew = descTextView.text
let frequencyOld = selectedFrequency
let viewController = segue.destination as! ShowTableViewController
viewController.userImage = userImageOld
viewController.userTitle = userTitleNew!
viewController.userDesc = userDescNew!
viewController.frequency = frequencyOld
}
if segue.identifier == "iconSelect" {
let userImageOld = selectedImage
let userTitleNew = titleTextField.text
let userDescNew = descTextView.text
let frequencyOld = selectedFrequency
let viewController = segue.destination as! IconTableViewController
viewController.userImage = userImageOld
viewController.userTitle = userTitleNew!
viewController.userDesc = userDescNew!
viewController.frequency = frequencyOld
}
}
Thank you very much for your help!
Seems like NewItemTableViewControlleris not yet top viewController on the navigation stack. Try accessing it in the same trivial way,
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let viewController = segue.destination as? NewItemTableViewController {
let userImageNew = userImage
let userTitleOld = userTitle
let userDescOld = userDesc
let frequencyOld = frequency
viewController.selectedImage = userImageNew
viewController.userTitle = userTitleOld
viewController.userDesc = userDescOld
viewController.selectedFrequency = frequencyOld
}
}
You should put a breakpoint inside above method prepare(for segue and see if it is being called. Because i feel you don't have unwind segue as these viewControllers are just pushed on the navigation stack. So in that case you can also use viewWillDisappear to set the data by accessing NewItemTableViewController from the navigation stack. Something as below,
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if let vc = self.navigationController?.viewControllers.first(where: { $0 is NewItemTableViewController }) as? NewItemTableViewController {
// Set data.
}
}
You should use Delegate to push data back to NewItemTableViewController. You can refer this thread: Pass data back to previous viewcontrolle
I have my custom TabBarController as usual, which contains 8 viewController.
class STTabBarController: UITabBarController,UITabBarControllerDelegate {
let tabBarOrderKey = "tabBarOrderKey"
private var messangerNavigationController: UINavigationController!
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self
configureViewControllers()
setUpTabBarItemTags()
getSavedTabBarItemsOrder()
}
func configureViewControllers() {
let clientsController = STClientsViewController(nibName: "STClientsViewController", bundle: nil)
let clientNavigationController = UINavigationController(rootViewController: clientsController)
clientsController.title = "Clients"
clientNavigationController.tabBarItem.image = UIImage(named: "Client")
let openHouseController = STOpenHouseViewController(nibName: "STOpenHouseViewController", bundle: nil)
let openHouseNavigationController = UINavigationController(rootViewController: openHouseController)
openHouseController.title = "Open House"
openHouseNavigationController.tabBarItem.image = UIImage(named: "OpenHouse")
let performanceController = STChartsViewController(nibName: "STChartsViewController", bundle: nil)
let performanceNavigationController = UINavigationController(rootViewController: performanceController)
performanceController.title = "Performance"
performanceNavigationController.tabBarItem.image = UIImage(named: "Performance")
let calculatorsController = STCalculatorsViewController(nibName: "STCalculatorsViewController", bundle: nil)
let calculatorsNavigationController = UINavigationController(rootViewController: calculatorsController)
calculatorsController.title = "Calculators"
calculatorsNavigationController.tabBarItem.image = UIImage(named: "Calculators")
let storyBoard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let communityViewController = storyBoard.instantiateViewController(withIdentifier: "Navigation")
communityViewController.title = "Community"
communityViewController.tabBarItem.image = UIImage (named:"Community")
let industryProfessionalsController = STIndustryProfessionalsViewController(nibName: "STIndustryProfessionalsViewController", bundle: nil)
let industryProfessionalsNavigationController = UINavigationController(rootViewController: industryProfessionalsController)
industryProfessionalsController.title = "Vendors"
industryProfessionalsNavigationController.title = "Vendors"
industryProfessionalsNavigationController.tabBarItem.image = UIImage(named: "Industry-professionals")
let agentResourcesController = STAgentResourcesViewController(nibName: "STAgentResourcesViewController", bundle: nil)
let agentResourcesNavigationController = UINavigationController(rootViewController: agentResourcesController)
agentResourcesController.title = "Resources"
agentResourcesNavigationController.title = "Resources"
agentResourcesNavigationController.tabBarItem.image = UIImage(named: "Agent-Resources")
let settingsController = STSettingsViewController(nibName: "STSettingsViewController", bundle: nil)
let settingsNavigationController = UINavigationController(rootViewController: settingsController)
settingsController.title = "Settings"
settingsNavigationController.tabBarItem.image = UIImage(named: "Settings")
let coachController = STCoachsCornerViewController(nibName: "STCoachsCornerViewController", bundle: nil)
let coachNavigationController = UINavigationController(rootViewController: coachController)
coachController.navigationItem.title = "Action Plan"
coachNavigationController.tabBarItem.title = "Plan"
coachNavigationController.tabBarItem.image = UIImage(named: "Plan")
self.viewControllers = [clientNavigationController ,performanceNavigationController,calculatorsNavigationController, coachNavigationController,industryProfessionalsNavigationController,agentResourcesNavigationController,openHouseNavigationController, settingsNavigationController]
tabBar.isTranslucent = false
let topBorder = CALayer()
topBorder.frame = CGRect(x: 0, y: 0, width: 1000, height: 0.5)
topBorder.backgroundColor = UIColor.returnRGBColor(r: 229, g: 231, b: 235, alpha: 1).cgColor
tabBar.layer.addSublayer(topBorder)
tabBar.clipsToBounds = true
}
func setUpTabBarItemTags() {
var tag = 0
if let viewControllers = viewControllers {
for view in viewControllers {
view.tabBarItem.tag = tag
tag += 1
}
}
}
func getSavedTabBarItemsOrder() {
var newViewControllerOrder = [UIViewController]()
if let initialViewControllers = viewControllers {
if let tabBarOrder = UserDefaults.standard.object(forKey: tabBarOrderKey) as? [Int] {
for tag in tabBarOrder {
newViewControllerOrder.append(initialViewControllers[tag])
}
setViewControllers(newViewControllerOrder, animated: false)
}
}
}
func tabBarController(_ tabBarController: UITabBarController, didEndCustomizing viewControllers: [UIViewController], changed: Bool) {
var orderedTagItems = [Int]()
if changed {
for viewController in viewControllers {
let tag = viewController.tabBarItem.tag
orderedTagItems.append(tag)
}
UserDefaults.standard.set(orderedTagItems, forKey: tabBarOrderKey)
}
}
And I met the problem when I start my on different devices and from time to time it can hide Settings(last) item in "More" tab.This look kinda ridiculous because code is straightforward and simple as you see and I dont know what can be wrong here.
Does smb know what can it be? Thanks
The problem was in saving order of this tabs to User Defaults.
I had 7 controllers, but when was trying to save it, saved was only 6.
Here is final code of saving function:
func getSavedTabBarItemsOrder() {
var newViewControllerOrder = [UIViewController]()
if let initialViewControllers = viewControllers {
if let tabBarOrder = UserDefaults.standard.object(forKey: tabBarOrderKey) as? [Int] {
for tag in tabBarOrder {
newViewControllerOrder.append(initialViewControllers[tag])
}
let difference = Set(initialViewControllers).subtracting(newViewControllerOrder)
newViewControllerOrder.append(contentsOf: difference)
setViewControllers(newViewControllerOrder, animated: false)
}
}
}
#IBAction func addToCart(sender: AnyObject) {
let itemObjectTitle = itemObject.valueForKey("itemDescription") as! String
let alertController = UIAlertController(title: "Add \(itemObjectTitle) to cart?", message: "", preferredStyle: .Alert)
let yesAction = UIAlertAction(title: "Yes", style: UIAlertActionStyle.Default) { (action) in
var tabArray = self.tabBarController?.tabBar.items as NSArray!
var tabItem = tabArray.objectAtIndex(1) as! UITabBarItem
let badgeValue = "1"
if let x = badgeValue.toInt() {
tabItem.badgeValue = "\(x)"
}
}
I don't know why I can't just do += "(x)"
Error:
binary operator '+=' cannot be applied to operands of type 'String?' and 'String'
I want it to increment by 1 each time the user selects "Yes". Right now obviously it just stays at 1.
You can try to access the badgeValue and convert it to Integer as follow:
Swift 2
if let badgeValue = tabBarController?.tabBar.items?[1].badgeValue,
nextValue = Int(badgeValue)?.successor() {
tabBarController?.tabBar.items?[1].badgeValue = String(nextValue)
} else {
tabBarController?.tabBar.items?[1].badgeValue = "1"
}
Swift 3 or later
if let badgeValue = tabBarController?.tabBar.items?[1].badgeValue,
let value = Int(badgeValue) {
tabBarController?.tabBar.items?[1].badgeValue = String(value + 1)
} else {
tabBarController?.tabBar.items?[1].badgeValue = "1"
}
To delete the badge just assign nil to the badgeValue overriding viewDidAppear method:
override func viewDidAppear(animated: Bool) {
tabBarController?.tabBar.items?[1].badgeValue = nil
}
Works with Swift 2:
let tabController = UIApplication.sharedApplication().windows.first?.rootViewController as? UITabBarController
let tabArray = tabController!.tabBar.items as NSArray!
let alertTabItem = tabArray.objectAtIndex(2) as! UITabBarItem
if let badgeValue = (alertTabItem.badgeValue) {
let intValue = Int(badgeValue)
alertTabItem.badgeValue = (intValue! + 1).description
print(intValue)
} else {
alertTabItem.badgeValue = "1"
}
#IBAction func addToCart(sender: AnyObject) {
let itemObjectTitle = itemObject.valueForKey("itemDescription") as! String
let alertController = UIAlertController(title: "Add \(itemObjectTitle) to cart?", message: "", preferredStyle: .Alert)
let yesAction = UIAlertAction(title: "Yes", style: UIAlertActionStyle.Default) { (action) in
var tabArray = self.tabBarController?.tabBar.items as NSArray!
var tabItem = tabArray.objectAtIndex(1) as! UITabBarItem
let badgeValue = "1"
if let x = badgeValue.toInt() {
tabItem.badgeValue = "\(x)"
}
}
I don't know why I can't just do += "(x)"
Error:
binary operator '+=' cannot be applied to operands of type 'String?' and 'String'
I want it to increment by 1 each time the user selects "Yes". Right now obviously it just stays at 1.
You can try to access the badgeValue and convert it to Integer as follow:
Swift 2
if let badgeValue = tabBarController?.tabBar.items?[1].badgeValue,
nextValue = Int(badgeValue)?.successor() {
tabBarController?.tabBar.items?[1].badgeValue = String(nextValue)
} else {
tabBarController?.tabBar.items?[1].badgeValue = "1"
}
Swift 3 or later
if let badgeValue = tabBarController?.tabBar.items?[1].badgeValue,
let value = Int(badgeValue) {
tabBarController?.tabBar.items?[1].badgeValue = String(value + 1)
} else {
tabBarController?.tabBar.items?[1].badgeValue = "1"
}
To delete the badge just assign nil to the badgeValue overriding viewDidAppear method:
override func viewDidAppear(animated: Bool) {
tabBarController?.tabBar.items?[1].badgeValue = nil
}
Works with Swift 2:
let tabController = UIApplication.sharedApplication().windows.first?.rootViewController as? UITabBarController
let tabArray = tabController!.tabBar.items as NSArray!
let alertTabItem = tabArray.objectAtIndex(2) as! UITabBarItem
if let badgeValue = (alertTabItem.badgeValue) {
let intValue = Int(badgeValue)
alertTabItem.badgeValue = (intValue! + 1).description
print(intValue)
} else {
alertTabItem.badgeValue = "1"
}