#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
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
}
}
I have a follow/unfollow button and am accessing it by "sender". I am changing the text when the user taps it to follow or unfollow another user. Problem is that when it should show "unfollow" it is showing the default text used in storyboard. The button changes to "follow" as it should, but not "unfollow". Also, I have to use "sender: UIButton" because I am accessing the tableview cells "tag" for the right information.
#IBAction func followButton(_ sender: UIButton) {
//self.yourFollowing.removeAll()
//self.following.removeAll()
self.followingTableView.reloadData()
let accessData = self.yourFollowing[sender.tag].dataPass
let businessUid = accessData["uid"] as! String
let businessName = accessData["businessName"] as! String
let businessStreet = accessData["businessStreet"] as! String
let businessCity = accessData["businessCity"] as! String
let businessState = accessData["businessState"] as! String
let businessZip = accessData["businessZIP"] as! String
let businessPhone = accessData["businessPhone"] as! String
let businessLatitude = accessData["businessLatitude"] as! String
let businessLongitude = accessData["businessLongitude"] as! String
let businessWebsite = accessData["businessWebsite"] as! String
let businessFacebook = accessData["facebookURL"] as! String
let businessFoursquare = accessData["foursquareURL"] as! String
let businessGoogle = accessData["googleURL"] as! String
let businessInstagram = accessData["instagramURL"] as! String
let businessSnapchat = accessData["snapchatURL"] as! String
let businessTwitter = accessData["twitterURL"] as! String
let businessYelp = accessData["yelpURL"] as! String
let userID = Auth.auth().currentUser!.uid
let ref = Database.database().reference()
let key = ref.child("Businesses").childByAutoId().key
var isFollower = false
let followersRef = "followers/\(businessUid)/\(self.loggedInUserData?["uid"] as! String)"
let followingRef = "following/" + (self.loggedInUserData?["uid"] as! String) + "/" + (businessUid)
ref.child("Businesses").child(userID).child("following").queryOrderedByKey().observeSingleEvent(of: .value, with: { snapshot in
if let following = snapshot.value as? [String : AnyObject] {
for (item, value) in following {
if value as! String == businessUid {
isFollower = true
let followersRef = "followers/\(businessUid)/\(self.loggedInUserData?["uid"] as! String)"
let followingRef = "following/" + (self.loggedInUserData?["uid"] as! String) + "/" + (businessUid)
let childUpdates = [followingRef:NSNull(),followersRef:NSNull()]
self.databaseRef.updateChildValues(childUpdates)
ref.child("Businesses").child(userID).child("following/\(item)").removeValue()
ref.child("Businesses").child(businessUid).child("followers/\(item)").removeValue()
sender.titleLabel?.text = "follow"
//self.yourFollowing.removeAll()
self.following.removeAll()
self.followingTableView.reloadData()
}
}
}
// Follow
if !isFollower {
sender.titleLabel?.text = "unfollow"
let followersData = ["email":self.loggedInUserData?["email"] as! String, "businessName":self.loggedInUserData?["businessName"] as! String]
let followingData = ["businessName":businessName, "businessStreet":businessStreet, "businessCity":businessCity, "businessState":businessState, "businessZIP":businessZip, "businessPhone":businessPhone, "businessWebsite":businessWebsite,"businessLatitude":businessLatitude, "businessLongitude":businessLongitude, "facebookURL":businessFacebook, "twitterURL":businessTwitter, "instagramURL":businessInstagram, "googleURL":businessGoogle, "yelpURL":businessYelp, "foursquareURL":businessFoursquare, "snapchatURL":businessSnapchat, "uid":businessUid]
let childUpdates = [followersRef:followersData, followingRef:followingData]
self.databaseRef.updateChildValues(childUpdates)
let following = ["following/\(key)" : businessUid]
let followers = ["followers/\(key)" : userID]
ref.child("Businesses").child(userID).updateChildValues(following as Any as! [AnyHashable : Any])
ref.child("Businesses").child(businessUid).updateChildValues(followers)
self.yourFollowing.removeAll()
self.following.removeAll()
self.followingTableView.reloadData()
}
})
}
Your problem is this line in your button action
#IBAction func followButton(_ sender: UIButton) {
.
.
var isFollower = false
.
.
}
You are declaring the variable isFollow inside the button action. This means that every time regardless of follow or unfollow, your isFollower is false which is why the condition for follow will work. But the change to true which is inside the completion of follow won't reflect next time you click the button because you are resetting isFollower to false.
Solution: Move the variable isFollow outside the button action.
var isFollow = false
#IBAction func followButton(_ sender: UIButton) {
// Your logic
}
Also your logic inside the completion seems wrong. Something like the code below should be there to change it to false.
if value as! String == businessUid {
isFollower = !isFollower
if isFollower {
// Follow logic
sender.setTitle("unfollow", for: .normal)
} else {
// Unfollowed logic
sender.setTitle("follow", for: .normal)
}
// Reload table
}
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)
}
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)
#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"
}