Increment tab bar badge w/ UIAlertAction swift? - ios

#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"
}

Related

Im trying to get the data entered to do calculation and display in a label

I am trying to get The Information that is added to display in a label on the main screen. I want it to calculate the profit but i get the error " Value of type 'String' has no member 'text' "
#IBAction func addButtonTapped(_ sender: Any) {
let alert = UIAlertController(title: "Product Information", message: nil, preferredStyle: .alert)
alert.addTextField(configurationHandler: { (itemTextField) -> Void in
itemTextField.placeholder = "Item"
})
alert.addTextField(configurationHandler: { (priceTextField) -> Void in
priceTextField.placeholder = "Price"
})
alert.addTextField(configurationHandler: { (salePriceTextField) -> Void in
salePriceTextField.placeholder = "Sale Price"
})
alert.addAction(UIAlertAction(title: "Add", style: .default) { (action) in
let item = alert.textFields?[0].text ?? ""
let price = alert.textFields?[1].text ?? ""
let salesPrice = alert.textFields?[2].text ?? ""
let itemPriceLabel = Double(price.text!)
let salePriceLabel = Double(salesPrice.text!)
if itemPriceLabel != nil && salePriceLabel != nil {
let profitValue = Double (itemPriceLabel! - salePriceLabel!)
ProfitLabel.text = profitValue
}
let product = Product(item: item, price: price, salesPrice: salesPrice)
self.addProduct(product)
})
self.present(alert, animated: true, completion: nil)
storeData()
}
Your price and salesPrice variables are already string only. But you’ve tried to access text field in those variables which is not present in String class in the next statement.
let itemPriceLabel = Double(price)
let salePriceLabel = Double(salesPrice)
And assign your value as follows.
ProfitLabel.text = String(profitValue)
Basically, both price and salesPrice are already Strings (because they took the text from the labels), not labels.
All you need to do is convert them to straight to doubles, no need for .text.
So instead of:
let itemPriceLabel = Double(price.text!)
let salePriceLabel = Double(salesPrice.text!)
Do:
let itemPriceLabel = Double(price)
let salePriceLabel = Double(salesPrice)
There are a few mistakes in the alert action and the naming of the variables is confusing, replace it with
alert.addAction(UIAlertAction(title: "Add", style: .default) { _ in
let itemText = alert.textFields?[0].text ?? ""
let priceText = alert.textFields?[1].text ?? ""
let salesPriceText = alert.textFields?[2].text ?? ""
if let price = Double(priceText),
let salesPrice = Double(salesPriceText),
!itemText.isEmpty {
let profitValue = price - salesPrice
ProfitLabel.text = String(profitValue)
let product = Product(item: itemText, price: price, salesPrice: salesPrice)
self.addProduct(product)
} else {
print("Enter something in 'item' and enter numeric values in 'price' and 'sales price'")
// add error handling
}
}

How to detect if UI Label was tapped?

I'm trying to make a choose-your-own adventure game that changes the text of two labels (the user choices) depending on which label the user taps. I figured I would just do a very nested if-else statement rather than bother with trying to implement a binary tree. I know how to attach the gesture recognizer to a label (I think):
let tapped1 = UITapGestureRecognizer(target: self, action: #selector(VCGame.usrChose1))
choice1.isUserInteractionEnabled = true
choice1.addGestureRecognizer(tapped1)
let tapped2 = UITapGestureRecognizer(target: self, action: #selector(VCGame.usrChose2))
choice2.isUserInteractionEnabled = true
choice2.addGestureRecognizer(tapped2)
and I can define what to do when the label is touched in the usrChose1 and usrChose2 functions, however, those functions only work once: the first time the function is chosen and my game has more than just one choice. From there, the labels will just do the same thing if the user touches them.
How would I go about having a condition inside the if-else statement that evaluates to true or false if label1 or label2 is tapped?
Here's the code for usrChoice1 and usrChoice2, for clarification
func usrChose1(sender : UITapGestureRecognizer) {
print("tap 1 working")
choice1.text = "choice1.1"
choice2.text = "choice1.2"
}
func usrChose2(sender : UITapGestureRecognizer) {
print("tap2 working")
choice1.text = "update2.1";
choice2.text = "update2.2"
}
Below image shows my requirement :
According to your requirement, I have tried the following:
I have made a dummy project with two labels inside a view controller
ViewController.swift
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var choice1Label: UILabel!
#IBOutlet weak var choiceLabel2: UILabel!
var tapStart: Bool = false
var levelType1: Level?
var levelType2: Level?
override func viewDidLoad() {
super.viewDidLoad()
let tapped1 = UITapGestureRecognizer(target: self, action: #selector(usrChose1))
choice1Label.isUserInteractionEnabled = true
choice1Label.addGestureRecognizer(tapped1)
let tapped2 = UITapGestureRecognizer(target: self, action: #selector(usrChose2))
choiceLabel2.isUserInteractionEnabled = true
choiceLabel2.addGestureRecognizer(tapped2)
setup()
}
var currentLevel1: Level?
var currentLevel2: Level?
func setup() {
let lb2Child1Child1 = Level(text: "2.1.1", subLevels: nil)
let lb2Child1Child2 = Level(text: "2.1.2", subLevels: nil)
let lb1Child1Child1 = Level(text: "1.1.1", subLevels: nil)
let lb1Child1Child2 = Level(text: "1.1.2", subLevels: nil)
let lb1Child2Child1 = Level(text: "1.2.1", subLevels: nil)
let lb1Child2Child2 = Level(text: "1.2.2", subLevels: nil)
let lb1Child1 = Level(text: "1.1", subLevels: [lb1Child1Child1, lb1Child1Child2])
let lb1Child2 = Level(text: "1.2", subLevels: [lb1Child2Child1, lb1Child2Child2])
let lb2Child1 = Level(text: "2.1", subLevels: [lb2Child1Child1, lb2Child1Child2])
let lb2Child2 = Level(text: "2.2", subLevels: nil)
levelType1 = Level(text: "1", subLevels: [lb1Child1, lb1Child2])
levelType2 = Level(text: "2", subLevels: [lb2Child1, lb2Child2])
choice1Label.text = levelType1!.text ?? ""
choiceLabel2.text = levelType2!.text ?? ""
}
func usrChose1(sender : UITapGestureRecognizer) {
if !tapStart {
currentLevel1 = levelType1
tapStart = true
}
if let subLevelsArray = currentLevel1?.subLevels {
print(subLevelsArray[0].text ?? "")
print(subLevelsArray[1].text ?? "")
choice1Label.text = subLevelsArray[0].text ?? ""
choiceLabel2.text = subLevelsArray[1].text ?? ""
currentLevel1 = subLevelsArray[0]
currentLevel2 = subLevelsArray[1]
}
}
func usrChose2(sender : UITapGestureRecognizer) {
//print("tap2 working")
// choice1Label.text = "update2.1";
//choiceLabel2.text = "update2.2"
if !tapStart {
currentLevel2 = levelType2
tapStart = true
}
if let subLevelsArray = currentLevel2?.subLevels {
print(subLevelsArray[0].text ?? "")
print(subLevelsArray[1].text ?? "")
choice1Label.text = subLevelsArray[0].text ?? ""
choiceLabel2.text = subLevelsArray[1].text ?? ""
currentLevel1 = subLevelsArray[0]
currentLevel2 = subLevelsArray[1]
}
}
}
I have made a class named Level to represent a single level and each level contains sublevels
Level.swift
import UIKit
class Level {
var text: String?
var subLevels: [Level]?
init(text: String, subLevels: [Level]?) {
self.text = text
self.subLevels = subLevels ?? nil
}
}
You have to add UITapGestureRecognizer in UILabel or UIView whatever is container.
Add 2 different Int variables in each functions usrChose1 and usrChose2 respectively, which will be work as a counter.
var i = 0
var j = 0
func usrChose1(_ recognizer: UITapGestureRecognizer) {
i++
print("Total clicked label 1 :::",i)
}
func usrChose2(_ recognizer: UITapGestureRecognizer) {
j++
print("Total clicked label 2 :::",j)
}

Material TextField previous next button

I am trying to get the previous/next arrow button on top of the keyboard when ever a textField is selected.
I have tried the following
textField0.tag = 0 // textField0 : TextField
textField0.addPreviousNextRightOnKeyboardWithTarget(self, rightButtonTitle: "Submit", previousAction: #selector(previousTextField(sender:)), nextAction: #selector(nextTextField(sender:)), rightButtonAction: #selector(saveNewPlan), titleText: nil)
textField1.tag = 1
textField1.addPreviousNextRightOnKeyboardWithTarget(self, rightButtonTitle: "Submit", previousAction: #selector(previousTextField(sender:)), nextAction: #selector(nextTextField(sender:)), rightButtonAction: #selector(saveNewPlan), titleText: nil)
The previous/next action selector defined as such.
func previousTextField(sender: AnyObject){
// I actually get the sender as IQBarButtonItem (subclass of UIBarButtonItem) instead of UITextField here
if let previousField = textField.superview?.viewWithTag(textField.tag - 1) as? UITextField {
_ = previousField.becomeFirstResponder()
}
}
func nextTextField(sender: AnyObject){
if let nextField = textField.superview?.viewWithTag(textField.tag + 1) as? UITextField {
_ = nextField.becomeFirstResponder()
}
}
It's throwing this error whenever I click on the button.
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[IQKeyboardManagerSwift.IQBarButtonItem superview]: unrecognized selector sent to instance 0x7fc3775658e0'
Here's what the method do.
public func addPreviousNextRightOnKeyboardWithTarget( _ target : AnyObject?, rightButtonTitle : String, previousAction : Selector, nextAction : Selector, rightButtonAction : Selector, titleText : String?) {
//If can't set InputAccessoryView. Then return
if self.responds(to: #selector(setter: UITextField.inputAccessoryView)) {
// Creating a toolBar for phoneNumber keyboard
let toolbar = IQToolbar()
toolbar.doneTitle = rightButtonTitle
var items : [UIBarButtonItem] = []
let prev : IQBarButtonItem
let next : IQBarButtonItem
// Get the top level "bundle" which may actually be the framework
var bundle = Bundle(for: IQKeyboardManager.self)
if let resourcePath = bundle.path(forResource: "IQKeyboardManager", ofType: "bundle") {
if let resourcesBundle = Bundle(path: resourcePath) {
bundle = resourcesBundle
}
}
var imageLeftArrow : UIImage!
var imageRightArrow : UIImage!
if #available(iOS 10.0, *) {
imageLeftArrow = UIImage(named: "IQButtonBarArrowUp", in: bundle, compatibleWith: nil)
imageRightArrow = UIImage(named: "IQButtonBarArrowDown", in: bundle, compatibleWith: nil)
} else {
imageLeftArrow = UIImage(named: "IQButtonBarArrowLeft", in: bundle, compatibleWith: nil)
imageRightArrow = UIImage(named: "IQButtonBarArrowRight", in: bundle, compatibleWith: nil)
}
//Support for RTL languages like Arabic, Persia etc... (Bug ID: #448)
if #available(iOS 9.0, *) {
imageLeftArrow = imageLeftArrow?.imageFlippedForRightToLeftLayoutDirection()
imageRightArrow = imageRightArrow?.imageFlippedForRightToLeftLayoutDirection()
}
prev = IQBarButtonItem(image: imageLeftArrow, style: UIBarButtonItemStyle.plain, target: target, action: previousAction)
prev.accessibilityLabel = "Toolbar Previous Button"
next = IQBarButtonItem(image: imageRightArrow, style: UIBarButtonItemStyle.plain, target: target, action: nextAction)
next.accessibilityLabel = "Toolbar Next Button"
//Previous button
items.append(prev)
//Fixed space
let fixed = IQBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.fixedSpace, target: nil, action: nil)
if #available(iOS 10.0, *) {
fixed.width = 6
} else {
fixed.width = 20
}
items.append(fixed)
//Next button
items.append(next)
//Flexible space
items.append(UIView.flexibleBarButtonItem())
//Title button
let title = IQTitleBarButtonItem(title: shouldHidePlaceholderText == true ? nil : titleText)
items.append(title)
//Flexible space
items.append(UIView.flexibleBarButtonItem())
//Right button
let doneButton = IQBarButtonItem(title: rightButtonTitle, style: UIBarButtonItemStyle.done, target: target, action: rightButtonAction)
items.append(doneButton)
// Adding button to toolBar.
toolbar.items = items
toolbar.toolbarTitleInvocation = self.titleInvocation
// Setting toolbar to keyboard.
if let textField = self as? UITextField {
textField.inputAccessoryView = toolbar
switch textField.keyboardAppearance {
case UIKeyboardAppearance.dark:
toolbar.barStyle = UIBarStyle.black
default:
toolbar.barStyle = UIBarStyle.default
}
} else if let textView = self as? UITextView {
textView.inputAccessoryView = toolbar
switch textView.keyboardAppearance {
case UIKeyboardAppearance.dark:
toolbar.barStyle = UIBarStyle.black
default:
toolbar.barStyle = UIBarStyle.default
}
}
}
}

Switch tab bar include sending data

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)

Swift 3 increment increment tab bar badge [duplicate]

#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"
}

Resources