How to get UIButton name in swift5? - ios

I am currently making a pin-code. I want to incorporate all the functions into one function, in order to integrate the button event function into one So I want to get the name of UIButton, but I don't know how.
#IBOutlet weak var oneButton: UIButton!
#IBOutlet weak var twoButton: UIButton!
...
var pinCodeNum : String! = ""
...
#IBAction func OneButton(_ sender: UIButton) {
pincodeLogic(sender)
}
func pincodeLogic(_ sender: UIButton) {
// I want get value is (example : 'oneButton' or 'twoButton' or 'threeButton' more )
}
As you can see from my code, I'm getting a 'sender' as a parameter I want to know the name of oneButton or twoButton using this parameter. How do I know?
My number button consists of a button and a label.
EDit
#IBAction func OneButton(_ sender: UIButton) {
pincodeLogic(sender)
}
func pincodeLogic(_ sender: UIButton) {
if let number = sender.currentTitle {
print(number)
}
}
I can't see the print log.

You can compare the sender with your button instances.
func pincodeLogic(_ sender: UIButton) {
switch sender {
case oneButton:
print("oneButton pressed")
case twoButton:
print("twoButton pressed")
default:
print("unknown button pressed")
}
}

To access the contents of the label present in the button using the sender, this is an example:
#IBAction func OneButton(_ sender: UIButton) {
print(sender.titleLabel?.text)
}
so you could do this:
#IBAction func OneButton(_ sender: UIButton) {
pincodeLogic(sender)
}
func pincodeLogic(_ sender: UIButton) {
if let number = sender.titleLabel?.text {
print(number)
}
}
I hope I've been there for you. Let me know.

if you want to access the button action to perform some specific task.Just put a tag with your each button and add the same target to all.
#IBAction func btnAction(_ sender: UIButton) {
switch sender.tag {
case 1:
print("oneButton pressed")
case 2:
print("twoButton pressed")
default:
print("unknown button pressed")
}
}
If you need just to print the button title the do the following.
#IBAction func btnAction(_ sender: UIButton) {
print(sender.titleLabel?.text! as! String)
}

#IBAction func btnClick(_ sender: UIButton{
print(sender.titleLabel!.text!)
}

Related

How to check who sent the message inside the IBAction

I want to use this IBAction func as a general func
#IBAction func test(_ sender: Any) {
}
How can I know that the sender is an UIButton?
You can set a different tag for each button. Then test which tag as the sender to know which button is tapped.
#IBAction func test(_ sender: Any) {
if let tag = (sender as? UIView).tag {
switch tag {
:/ add case for each tab value
}
}
}
try this
#IBAction func test(_ sender: Any) {
if let button = sender as? UIButton {
// Do something with button
}
// If you don't use the button
if sender is UIButton {
// Do something
}
}

Nightmare on Segue street

What the app should do:
1) The user types a word into a textField and taps the corresponding button
2) The app should segue to another scene containing two labels. One should display the word typed by the user, the other identifies the button tapped. These pieces of data should be passed via properties on the receiving ViewController.
What it actually does:
1) The segue is immediately invoked, apparently bypassing prepare(segue: sender:)
2) Both labels are blank
3) Breakpoints and print() indicate that prepare(segue: sender:) is never called
What I've checked/tried:
1) The buttons have the correct tags in storyboard, according to my print() statements
2) I've substituted if else for switch
3) I'm pretty sure I've read every associated question and answer on SO
4) Switched sender in prepare(segue: sender:) from Any? to UIButton and back again
The code
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
#IBOutlet weak var textField: UITextField!
#IBOutlet weak var tf2: UITextField!
#IBOutlet weak var tf3: UITextField!
#IBOutlet weak var tf4: UITextField!
#IBAction func sendButton(_ sender: UIButton) {
print("sender.tag is \(sender.tag)")
self.performSegue(withIdentifier: "mySegue", sender: sender)
print("sender.tag is \(sender.tag)")
}
#IBAction func button2(_ sender: UIButton) {
print("sender.tag is \(sender.tag)")
self.performSegue(withIdentifier: "mySegue", sender: sender)
print("sender.tag is \(sender.tag)")
}
#IBAction func button3(_ sender: UIButton) {
print("sender.tag is \(sender.tag)")
self.performSegue(withIdentifier: "mySegue", sender: sender)
print("sender.tag is \(sender.tag)")
}
#IBAction func button4(_ sender: UIButton) {
print("sender.tag is \(sender.tag)")
self.performSegue(withIdentifier: "mySegue", sender: sender)
print("sender.tag is \(sender.tag)")
}
func prepare(for segue: UIStoryboardSegue, sender: UIButton) {
print("Inside prepare for segue")
print("sender.tag is \(sender.tag)")
if segue.identifier == "mySegue" {
let vc = segue.destination as! SecondViewController
print("sender.tag is \(sender.tag)")
switch sender.tag {
case 101:
if (textField.text?.count)! >= 1 {
vc.staticText = "Button 101"
vc.textProp = self.textField.text!
print("sender.tag is \(sender.tag)")
}
case 102:
if (tf2.text?.count)! >= 1 {
vc.staticText = "Button 102"
vc.textProp = self.tf2.text!
print("sender.tag is \(sender.tag)")
}
case 103:
if (tf3.text?.count)! >= 1 {
vc.staticText = "Button 103"
vc.textProp = self.tf3.text!
print("sender.tag is \(sender.tag)")
}
case 104:
if (tf4.text?.count)! >= 1 {
vc.staticText = "Button 104"
vc.textProp = self.tf4.text!
print("sender.tag is \(sender.tag)")
}
default:
print("Something went wrong")
}
// print("In FirstVC, vc.textProp = \(vc.textProp)")
}else{
print("No text in textField...")
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
I admit upfront that I'm pretty good at overlooking the obvious, but I did put in a lot of time before bugging you guys. Any help or direction will be very much appreciated...
Thanks!
prepare(for segue is not called because the signature is wrong. You must not change the type of the sender parameter.
Cast sender to the expected type in an extra line for example
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "mySegue",
let button = sender as? UIButton {
...
and replace all subsequent occurrences of sender with button

Swift Multiple buttons sending String through same segue

Looking for some clarification and just to double check if I am on the right path. I have a category list where multiple buttons will send a specific string through a segue. I have the IBOutlets for each button but want to make sure when that specific button is touched that specific string is sent. I am just unsure if the way I am setting up the segue is correct so that each button is specific to the set strings. So far, the current segue works for "attractionsButton" but when I tap other buttons it passes the same data. I know it's not set, but want to make sure that when another button is tapped its not sending the wrong string.
#IBOutlet weak var attractionsButton: UIButton!
#IBOutlet weak var eatingButton: UIButton!
#IBOutlet weak var financialButton: UIButton!
#IBOutlet weak var lodgingButton: UIButton!
#IBOutlet weak var medicalButton: UIButton!
#IBOutlet weak var publicButton: UIButton!
#IBOutlet weak var servicesButton: UIButton!
#IBOutlet weak var storesButton: UIButton!
#IBOutlet weak var transportationButton: UIButton!
let attractions = "Attractions & Entertainment"
let eating = "Eating & Drinking"
var financial = "Financial Institution"
var lodging = "Lodging Establishment"
var medical = "Medical & Health"
var publicService = "Public Services & Buildings"
var services = "Service"
var stores = "Stores & Shopping"
var transportation = "Transportation"
#IBAction func attractionsButton(_ sender: Any) {
performSegue(withIdentifier: "category", sender: self)
}
#IBAction func eatingButton(_ sender: Any) {
performSegue(withIdentifier: "category", sender: self)
}
#IBAction func financialButton(_ sender: Any) {
performSegue(withIdentifier: "category", sender: self)
}
#IBAction func lodgingButton(_ sender: Any) {
performSegue(withIdentifier: "category", sender: self)
}
#IBAction func medicalButton(_ sender: Any) {
performSegue(withIdentifier: "category", sender: self)
}
#IBAction func publicButton(_ sender: Any) {
performSegue(withIdentifier: "category", sender: self)
}
#IBAction func serviceButton(_ sender: Any) {
performSegue(withIdentifier: "category", sender: self)
}
#IBAction func storesButton(_ sender: Any) {
performSegue(withIdentifier: "category", sender: self)
}
#IBAction func transportationButton(_ sender: Any) {
performSegue(withIdentifier: "category", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
if segue.identifier == "category" {
if let button1 = attractionsButton {
let user = attractions
let controller = segue.destination as? CategoryListedViewController
controller?.categoryList = user
}
}
}
change self in your action to sender, you can use this one action for all the buttons
#IBAction func transportationButton(_ sender: Any) {
performSegue(withIdentifier: "category", sender: sender)
}
use this code in your prepare for segue
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
if segue.identifier == "category" {
let senderButton = sender as! UIButton
switch senderButton{
case attractionsButton:
let user = attractions
let controller = segue.destination as? CategoryListedViewController
controller?.categoryList = user
case eatingButton:
//editing button scenario
print("editing button scenario")
default:
//default code
print("default scenario")
}
}
}
All of your buttons can connect to just this one #IBAction:
#IBAction func allButtons (_ sender: Any) {
performSegue(withIdentifier: "category", sender: sender)
}
Of course, if that is all the buttons are doing, you can skip using the #IBAction entirely and just wire the segues from the buttons directly. If you do that when creating the first button in the Storyboard, you can copy that button and all copies will be wired to the same segue.
Then in prepare(for:sender:), compare the sender to your #IBOutlets to set your string:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let button = sender as? UIButton,
let controller = segue.destination as? CategoryListedViewController,
segue.identifier == "category" {
let str: String
switch button {
case attractionsButton: str = attractions
case eatingButton: str = eating
case financialButton: str = financial
default: str = ""
}
controller.categoryList = str
}
}
If I were you I would use buttons tags and a good old enum to work this out:
First, in Interface Builder, you set the tag property of each of your buttons (and you don't even need to have them anymore as #IBOutlet)
1 for attractionsButton, 2 for eatingButton, etc.
Then, you create an enum, with raw value as Int with matching values :
enum Category : Int, CustomStringConvertible {
case attractions = 1
case eating = 2
case financial = 3
case lodging = 4
case medical = 5
case publicService = 6
case services = 7
case stores = 8
case transportation = 9
var description : String {
switch self {
case .attractions: return "Attractions & Entertainment"
case .eating: return "Eating & Drinking"
case .financial: return "Financial Institution"
case .lodging: return "Lodging Establishment"
case .medical: return "Medical & Health"
case .publicService: return "Public Services & Buildings"
case .services: return "Service"
case .stores: return "Stores & Shopping"
case .transportation: return "Transportation"
}
}
}
After that, you link all your buttons to only one #IBAction like this one:
#IBAction func onButtonTap(_ sender: UIButton) {
performSegue(withIdentifier: "category", sender: Category(rawValue: sender.tag))
}
This way, according to the tag of the button, you'll create the enum you need.
As an end, in your segue preparation, you can set things like that:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "category" {
guard
let controller = segue.destination as? CategoryListedViewController,
let category = sender as? Category
else { return }
controller.categoryList = category.description
}
}
This way, things are much more concise and you can attache more behaviors to your enum Category, use it in switches, and so on, instead of relying on Strings or multiplying copy&paste code.

Switch statement for UserDefaults (Swift-Xcode)

I would like to know how i could do a switch-case/any good statement for user defaults instead of using if-else because as you can see from my code, i'm using 3 if statements which is abit redundant and ugly.
The purpose of this view controller is for a "Pick a card" game, the user gets to pick 3 cards each time and if he/she selects a card, they will not be able to select that particular card again.
import UIKit
class ViewController: UIViewController {
#IBOutlet var buttona: UIButton!
#IBOutlet var buttonb: UIButton!
#IBOutlet var buttonc: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
if (UserDefaults.standard.integer(forKey: "dissapear") == 1)
{
buttona.setImage(UIImage(named: "wildcardbackingblack.png"), for: .normal)
buttona.isEnabled = false
}
if (UserDefaults.standard.integer(forKey: "dissapear2") == 1)
{
buttonb.setImage(UIImage(named: "wildcardbackingblack.png"), for: .normal)
buttonb.isEnabled = false
}
if (UserDefaults.standard.integer(forKey: "dissapear3") == 1)
{
buttonc.setImage(UIImage(named: "wildcardbackingblack.png"), for: .normal)
buttonc.isEnabled = false
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func Button1(_ sender: Any) {
UserDefaults.standard.set(1, forKey:"dissapear")
self.performSegue(withIdentifier: "show", sender: nil)
}
#IBAction func Button2(_ sender: Any) {
UserDefaults.standard.set(1, forKey:"dissapear2")
self.performSegue(withIdentifier: "show", sender: nil)
}
#IBAction func Button3(_ sender: Any) {
UserDefaults.standard.set(1, forKey:"dissapear3")
self.performSegue(withIdentifier: "show", sender: nil)
}
}
func updateCard(button: UIButton, image: String, isEnabled: Bool) {
DispatchQueue.main.asyc {
button.setImage(UIImage(named:image), for: .normal)
button.isEnabled = isEnabled
}
}
.
.
.
let option : Int = UserDefaults.standard.integer(forKey: "dissapear")
switch (option) {
case 1:
self.updateCard(button: ..., image:"wildcardbackingblack.png", isEnabled: false)
case 2:
self.updateCard(button: ..., image:"wildcardbackingblack.png", isEnabled: false)
case 3:
self.updateCard(button: ..., image:"wildcardbackingblack.png", isEnabled: false)
default:
self.updateCard(button: ..., image:"default.png", isEnabled: false)
}
//Save the different integer value in same key user defaults.
#IBAction func Button1(_ sender: Any) {
UserDefaults.standard.set(1, forKey:"dissapear")
self.performSegue(withIdentifier: "show", sender: nil)
}
#IBAction func Button2(_ sender: Any) {
UserDefaults.standard.set(2, forKey:"dissapear")
self.performSegue(withIdentifier: "show", sender: nil)
}
#IBAction func Button3(_ sender: Any) {
UserDefaults.standard.set(3, forKey:"dissapear")
self.performSegue(withIdentifier: "show", sender: nil)
}
Here is how I would write this code, if I were sticking to the same UserDefaults storage. Note: you need to reconnect cardPressed(_:) to every button/card
import UIKit
class ViewController: UIViewController {
#IBOutlet var buttonA: UIButton!
#IBOutlet var buttonB: UIButton!
#IBOutlet var buttonC: UIButton!
let buttonKeyPairs: [(button: UIButton, key: String)] = [
(buttonA, "dissapear"),
(buttonB, "dissapear2"),
(buttonC, "dissapear3"),
]
override func viewDidLoad() {
super.viewDidLoad()
for (button, key) in buttonKeyPairs
where UserDefaults.standard.integer(forKey: key) == 1 {
button.setImage(UIImage(named: "wildcardbackingblack.png"), for: .normal)
button.isEnabled = false
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func buttonPressed(_ sender: UIButton) {
let key: String
switch UIButton {
case buttonA: key = "dissapear"
case buttonB: key = "dissapear2"
case buttonC: key = "dissapear3"
}
UserDefaults.standard.set(1, forKey: key)
self.performSegue(withIdentifier: "show", sender: self)
}
}

How to call for button action, inside from another button action in swift 3.0

I have below button action
#IBAction func actionB(_ sender: UIButton) {
print("something")
}
and I want to call above button action inside below button action.
#IBAction func actionC(_ sender: UIButton) {
//call to above button action in here
}
how can I do that. hope your help with this
Try this :
#IBAction func actionC(sender: AnyObject) {
//call to above button action in here
actionB(sender: sender);
}
try this solution
actionB("")
if you want you can also do like this
actionB(sender)
or
actionB(ButtonB)
Just change your code to:
#IBAction func actionB(sender: AnyObject?) {
print("something")
actionC(nil)
}
#IBAction func actionC(sender: AnyObject?) {
//call to above button action in here
}
Notice the optional mark after AnyObject.
or
#IBAction func actionB(sender: AnyObject) {
print("something")
}
#IBAction func actionC(sender: AnyObject) {
//call to above button action in here
actionB("" as AnyObject)
}
Here is the way to do it ...
#objc fileprivate func methodA(_ sender: UIButton) {
print("method A")
}
#objc fileprivate func methodB(_ sender: UIButton) {
methodA(sender)
}

Resources