#IBAction
func buttonTapped(_ sender: UIBarButtonItem) {
guard let title = sender.currentTitle,
let button = Buttons(rawValue: title) else { return }
}
The error I am getting says “Value of type ‘UIBarButtonItem’ has no member ‘currentTitle’, I have enums and cases for each button too.
Try gaurd let title = sender.title
Related
while click on the button for the first time, the title of the button will get changed from "Add to Cart" to "Go to Cart". And from the next click the button will navigate to the next screen (cart page) [just like flipkart].
here is my piece of code:
#IBAction func addToCartbtnTapped(_ sender: Any) {
if let info = detailInfo {
let cartData = CartStruct(cartItems: info, cartQuantity: 1)
self.saveCart(data: cartData)
showAlert()
(sender as AnyObject).setTitle("Go to Cart", for: .normal)
let cart = self.storyboard?.instantiateViewController(withIdentifier: "CartViewController") as? CartViewController
self.navigationController?.pushViewController(cart!, animated: true)
}
}
I'm able to change the title of the button. But whenever I click on the button for nth number of time also, the product is getting added to the cart, screen is not navigating.
How to solve this issue?
Update..
override func viewDidLoad() {
super.viewDidLoad()
UserDefaults.standard.string(forKey: "btn")
}
#IBAction func addToCartbtnTapped(_ sender: Any) {
if !Clicked {
if let info = detailInfo {
let cartData = CartStruct(cartItems: info, cartQuantity: 1)
self.saveCart(data: cartData)
showAlert()
addingTOCart.setTitle("Go to Cart", for: .normal)
UserDefaults.standard.set("Go to Cart", forKey: "btn")
print("Clicked")
Clicked = true
return
}
}
if Clicked {
print("Perform Action")
let cart = self.storyboard?.instantiateViewController(withIdentifier: "CartViewController") as? CartViewController
self.navigationController?.pushViewController(cart!, animated: true)
}
}
This is how I am trying to store the "Go to Cart" state. But not working.. please suggest!
Add this code to check cart is already added or not, If added change title according in your detail controller:
override func viewWillAppear(_ animated: Bool) {
if let info = detailInfo {
let buttonTItle = (self.checkCartData(cartInfo: info) ? "Go to Cart" : "Add to Cart")
addToCartButton.setTitle(buttonTItle, for: .normal)
}
}
Next, Check before adding to cart. If already added, will navigate to cart page else add new cart item(changing button title too).
#IBAction func addToCartbtnTapped(_ sender: Any) {
if let info = detailInfo {
if checkCartData(cartInfo: info) {
let cart = self.storyboard?.instantiateViewController(withIdentifier: "CartViewController") as? CartViewController
self.navigationController?.pushViewController(cart!, animated: true)
} else {
let cartData = CartStruct(cartItems: info, cartQuantity: 1)
self.saveCart(data: cartData)
showAlert()
(sender as AnyObject).setTitle("Go to Cart", for: .normal)
}
}
}
Check Cart data here:
func checkCartData(cartInfo: jsonstruct) -> Bool {
guard let cart = self.getCartData() else { return false }
return (cart.contains(where: { $0.cartItems.name == cartInfo.name }) ? true : false )
}
Get all Cart Data with this method:
func getCartData() -> [CartStruct]? {
let defaults = UserDefaults.standard
var tempCart: [CartStruct]?
if let cdata = defaults.data(forKey: "cartt") {
tempCart = try! PropertyListDecoder().decode([CartStruct].self, from: cdata)
}
return tempCart
}
You can apply check on your button title for performing two different actions. Also you are showing alert and pushing View Controller at the same time which might be the reason for screen not navigating.
#IBAction func addToCartbtnTapped(_ sender: UIButton) {
if let info = detailInfo {
switch sender.currentTitle! {
case "Add to Cart":
let cartData = CartStruct(cartItems: info, cartQuantity: 1)
self.saveCart(data: cartData)
showAlert()
(sender as AnyObject).setTitle("Go to Cart", for: .normal)
case "Go to Cart":
let cartData = CartStruct(cartItems: info, cartQuantity: 1)
self.saveCart(data: cartData)
showAlert()
(sender as AnyObject).setTitle("Go to Cart", for: .normal)
default:
print("Default Case")
}
}
}
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var btn: UIButton!
var Clicked:Bool = false
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func btnClick(_ sender: Any) {
if !Clicked {
btn.setTitle("Click", for: .normal)
print("Clicked")
Clicked = true
return
}
if Clicked {
print("Perform Action")
}
}
}
These both button shows same ViewController.
ViewController1.swift
#objc func btnEdit()
{
print("Edit")
let editDeptt = self.storyboard?.instantiateViewController(withIdentifier: "Add Department") as! AddDepartmentVC
self.navigationController?.pushViewController(editDeptt, animated: true)
}
#IBAction func btnNewDeptt(_ sender: Any)
{
let addDepttVC = self.storyboard?.instantiateViewController(withIdentifier: "Add Department") as! AddDepartmentVC
self.navigationController?.pushViewController(addDepttVC, animated: true)
}
ViewController2.swift
override func viewDidLoad() {
super.viewDidLoad()
//How to identify i come from which button
}
Add a property to your AddApartmentVC called action and set it before you push the view controller.
First create an enum:
enum Action {
case edit, newDept, unknown
}
Then define this property in your AddApartmentVC:
var action = Action.unknown
Then in your buttons' actions, set the property to the desired value:
editDeptt.action = .edit
or
addDepttVC.action = .newDept
Finally, in viewDidLoad(), check the value:
override func viewDidLoad() {
super.viewDidLoad()
switch(action) {
case .edit:
// do something for edit
case .newDept
// create a new Dept
case .unknown
print("what am I doing here?")
}
}
Add an instance variable name identify in your AddDepartmentVC and pass set the value of the same from your current VC like this
let editDeptt = self.storyboard?.instantiateViewController(withIdentifier: "Add Department") as! AddDepartmentVC
editDeptt.identify = "button1"
Then you can push it and check the variable in AddDepartmentVC
In ViewController2.swift, declare one variable like this
class ViewController2: UIViewController{
let var originTag: Int = 0
}
override func viewDidLoad() {
super.viewDidLoad()
if originTag == 0
{
// come from button 1 - btnEdit
}
else
{
// come from button 2 - btnNewDeptt
}
}
In ViewController 1, set originTag like this.
#objc func btnEdit()
{
print("Edit")
let editDeptt = self.storyboard?.instantiateViewController(withIdentifier: "Add Department") as! AddDepartmentVC
editDeptt.originTag = 0
self.navigationController?.pushViewController(editDeptt, animated: true)
}
#IBAction func btnNewDeptt(_ sender: Any)
{
let addDepttVC = self.storyboard?.instantiateViewController(withIdentifier: "Add Department") as! AddDepartmentVC
addDepttVC.originTag = 1
self.navigationController?.pushViewController(addDepttVC, animated: true)
}
Simply assign a tag for button -
Button1.tag=1
Button2.tag=2
Then check your button -
func onClickButton(sender: UIButton){
switch(sender.tag){
case 101 :
print("I am from button 1")
default :
print("I am from button 2")
}
}
use following it's perfectly working for you.
Take one public variable above class like below in Viewcontroller1.Swift
public var btnComingFrom = "first"
#objc func btnEdit()
{
btnComingFrom = "first"
print("Edit")
let editDeptt =
self.storyboard?.instantiateViewController(withIdentifier: "Add Department")
as! AddDepartmentVC
self.navigationController?.pushViewController(editDeptt, animated: true)
}
#IBAction func btnNewDeptt(_ sender: Any)
{
btnComingFrom = "second"
let addDepttVC = self.storyboard?.instantiateViewController(withIdentifier: "Add Department") as! AddDepartmentVC
self.navigationController?.pushViewController(addDepttVC, animated: true)
}
ViewController2.swift
override func viewDidLoad()
{
super.viewDidLoad()
if btnComingFrom == "first"
{
print("you are coming from first button")
}
if btnComingFrom == "second"
{
print("you are coming from second button")
}
}
I have a TableView where I display all my data and each cell might have 1-2 buttons. I read many topics and understand how to add target for each button through my ViewController. Since these buttons will be forwarded to the same VC and display images, I have the following code. In my TableViewCell subclass I have 2 buttons
class CODetailsTicketCell: UITableViewCel {
var onButtonTapped: (() -> Void)? = nil
#IBAction func firstBtnTapped(_ sender: UIButton) {
if let onButtonTapped = self.onButtonTapped {
onButtonTapped()
}
print("First button was pressed")
}
#IBAction func secondBtnTapped(_ sender: UIButton) {
if let onButtonTapped = self.onButtonTapped {
onButtonTapped()
}
print("Second button was pressed")
}
}
In my ViewController in cellForRowAt indexPath I have the following code
let message = messages[indexPath.row]
if let cell = tableView.dequeueReusableCell(withIdentifier: "COTicketsCell", for: indexPath) as? CODetailsTicketCell {
cell.configureCell(openTickets: message)
cell.onButtonTapped = {
self.performSegue(withIdentifier: "toImageVC", sender: message)
}
return cell
In order to pass the data through segue I use the following code in prepareForSegue
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "toImageVC" {
let navigationController = segue.destination as? UINavigationController
if let targetController = navigationController?.topViewController as? ImageVC {
if let data = sender as? OpenTicketsData {
targetController.loadImageURL = URL(string: data.firstImageUrl)
}
}
}
}
Everything is working FINE but I can't check for button tag in prepareForSegue. Basically, currently both buttons send the same data
targetController.loadImageURL = URL(string: data.firstImageUrl)
How can I pass data based on the button pressed? I tried to do something like this but seems it's wrong and not working.
let button = sender as? UIButton
if let data = sender as? OpenTicketsData {
if button?.tag == 1 {
targetController.loadImageURL = URL(string: data.firstImageUrl)
} else if button?.tag == 2 {
targetController.loadImageURL = URL(string: data.secondImageUrl)
}
}
You can either separate it into 2 different events or
class CODetailsTicketCell: UITableViewCell {
var onButtonTapped: ((_ sender: UIButton) -> Void)? = nil
#IBAction func firstBtnTapped(_ sender: UIButton) {
if let onButtonTapped = self.onButtonTapped {
onButtonTapped?(sender)
}
print("First button was pressed")
}
#IBAction func secondBtnTapped(_ sender: UIButton) {
if let onButtonTapped = self.onButtonTapped {
onButtonTapped(sender)
}
print("Second button was pressed")
}
}
In your assignment of the onButtonTapped, remember to add [weak self] if you ever use self to avoid the retain cycle.
cell.onButtonTapped = { [weak self] sender in
if sender.tag == 1 {
// Do something
} else {
// Do other thing
}
}
I am trying to compare the title that I have in a button so that if it is compared to another it does a certain thing or not. I'm using the .setTitle function but I think in swift3 it gives error and I can not find the why. Then I leave a catch of the error to make it easier to see it and also the code itself. Thanks for the help
#IBAction func _login_button(_ sender: Any)
{
if(_login_button.titleLabel?.text == "OKEY")
{
let preferences = UserDefaults.standard
preferences.removeObject(forKey: "session")
LoginToDo()
return
}
let username = _username.text
let password = _password.text
if(username == "" || password == "")
{
return
}
DoLogin(username!, password!)
}
change your #IBAction func _login_button(_ sender: Any) to you need to type cast from Any to UIButton #IBAction func _login_button(_ sender: UIButton)
#IBAction func _login_button(_ sender: UIButton)
{
if(sender.titleLabel?.text == "OKEY")
{
}
}
_login_button is #IBAction you have to create the button for #IBOutlet of button
you need to get button as below , now you access function name instead of sender
#IBAction func _login_button(_ sender: Any)
let button: UIButton = sender as! UIButton
if(button.titleLabel?.text == "OKEY")
{
}
}
If you get this error as per screen shot, you need to type cast from Any to UIButton and then use titleLabel property.
Thanks for the help in advance. I don't know why when I try to make a phone call with a button function as below
#IBAction func phonebutton(_ sender: Any) {
guard let number1 = URL(string: "telprompt://\(phonenumber)") else { return }
UIApplication.shared.open(number1 as! URL, options: [:], completionHandler: nil)
}
it doesn't show anything.
To explain more, the String value "phonenumber" is transferred from another tableview cell prepare for segue function as below
override func prepare(for segue: UIStoryboardSegue, sender: Any? ) {
if (segue.identifier == "indooradventureseg"){
let transfertopage = segue.destination as! indooradventuretablecellViewController
transfertopage.phonenumber = info[sender as! Int][4] as! String
}
Here's the code in the ViewController where I put my call button in
class indooradventuretablecellViewController: UIViewController {
var phonenumber = "31617543"
override func viewDidLoad() {
super.viewDidLoad()
phonenumberlabel.text = phonenumber
phonebuttonlabel.setTitle(phonenumber, for: .normal)
}
However, if I put any other String initiated within the ViewController or simply put the phone number on the button function like below, the phone call function does work.
#IBAction func phonebutton(_ sender: Any) {
guard let number1 = URL(string: "telprompt://12345678") else { return }
UIApplication.shared.open(number1 as! URL, options: [:], completionHandler: nil)
}
Please help. Thanks!