How to check who sent the message inside the IBAction - ios

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

Related

How do I know in swift which button was pressed when different buttons lead to the same ViewController?

I have four buttons which all lead to the same view controller. I need to know which button was pressed, because the view controller is set up slightly different for each button.
I tried the following:
ViewController (called "SecondViewController") where one of the Buttons is pressed
var index = 0
#IBAction func Button1(_ sender: UIButton) {
index = 1
}
#IBAction func Button2(_ sender: UIButton) {
index = 2
}
#IBAction func Button3(_ sender: UIButton) {
index = 3
}
#IBAction func Button4(_ sender: UIButton) {
index = 4
}
func getIndex() -> Int{
return index
}
The view controller which will be opened afterwards
// to get functions from SecondViewController
var second = SecondViewController()
let index = second.getIndex()
print(index)
Unfortunately it always prints zero. I guess because I set the index to 0 in the beginning, but I do not understand why doesn't the value update, when the Button was pressed.
What can I do?
I guess you are using segues, so your segue is executing before your IBAction can update your index value. There is a similar question & solution here
So to fix this give your segue an identifier, and call performSegueWithIdentifier from within your IBAction methods.
SecondViewController (Previous one which contains buttons)
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let firstViewController = segue.destination as? FirstViewController {
firstViewController.index = self.index
}
}
FirstViewController (One should be displayed after buttons clicked)
var index: Int?
override func viewDidLoad() {
super.viewDidLoad()
print(index)
}
if I understand you correctly,you will definitely get index as 0.
var index = 0
#IBAction func Button1(_ sender: UIButton) {
index = 1
}
#IBAction func Button2(_ sender: UIButton) {
index = 2
}
#IBAction func Button3(_ sender: UIButton) {
index = 3
}
#IBAction func Button4(_ sender: UIButton) {
index = 4
}
func getIndex() -> Int{
return index
}
above code is in SecondViewController, right?
then you call code below in another view controller (maybe FirstViewController)
// to get functions from SecondViewController
var second = SecondViewController()
let index = second.getIndex()
print(index)
so you get index out of the SecondViewController after it just was initialized and there is no way you can click on buttons and change index before second.getIndex().

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

How to get UIButton name in swift5?

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!)
}

How do I pass specific text to a label depending on which UIButton is pressed?

I'm very new to coding and I'm having trouble passing data to a second view controller. I want to change a label in the second view controller depending on which button is pressed in the first (if you press art the label says "art museum", if you press rollercoaster the label says "theme park")
I have tried putting the override function into the brackets for the button but I got the error "override can only be specified on class members"
firstacCode
class firstacCode: UIViewController {
#IBAction func art(_ sender: Any) {
performSegue(withIdentifier: "artSegue", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let destVC : acCode = segue.destination as! acCode
destVC.descriptionLabel = "art museum"
}
acCode
class acCode: UIViewController {
var descriptionLabel :String = "";
#IBOutlet weak var descriptionText: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
descriptionText.text = descriptionLabel
// Do any additional setup after loading the view.
}
This worked for me for one button but I'm not sure how to add another button into the equation. Any help would be greatly appreciated.
First of all connect your buttons to the art function, from the attribute inspector give tags to the buttons.
Now your code will be look like this :
#IBAction func art(_ sender: UIButton) {
if sender.tag == 0{
performSegue(withIdentifier: "mySegue", sender: "art museum")
}
if sender.tag == 1{
performSegue(withIdentifier: "mySegue", sender: "Theme Park")
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let vc : acCode = segue.destination as! acCode
vc.destVc = sender as! String
}
First off, welcome to Stackoverflow. You're already doing the passing of data to the other controller correctly. So your only problem now I guess is how to handle multiple buttons in your IBAction function.
Tip:
You can actually make this #IBAction func art(_ sender: Any) as #IBAction func art(_ sender: UIButton). Instead of Any, turn it into UIButton to avoid casting.
Assuming you connected multiple buttons into that art IBAction function, you can catch that specific button object through your sender and pass that sender to the sender parameter of your prepareForSegue, or in your case, I just realized that you might have different function for your two buttons, just pass the string to that sender parameter.
So your code would be like so:
#IBAction func art(_ sender: Any) {
performSegue(withIdentifier: "artSegue", sender: "art museum")
}
#IBAction func rollercoaster(_ sender: Any) {
performSegue(withIdentifier: "artSegue", sender: "theme park")
}
and in your prepareForSegue, cast the sender to String.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let destVC : acCode = segue.destination as! acCode
destVC.descriptionLabel = sender as! String
}
#IBAction func art(_ sender: Any) {
sender.tag = 1
performSegue(withIdentifier: "artSegue", sender: self)
}
#IBAction func art2(_ sender: Any) {
sender.tag = 2
performSegue(withIdentifier: "art2Segue", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if(sender.tag == 1){
let destVC : acCode = segue.destination as! acCode
destVC.descriptionLabel = "art museum"
}
if(sender.tag == 2){
let destVC : acCode = segue.destination as! acCode
destVC.descriptionLabel = "art2 museum"
}
}

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