I have a function, setupGame(). When I press the play again button, the setupGame() function should be called. Where should I add this function?
let playAgain: UIButton = UIButton(frame: CGRectMake(-10, 400, 400, 150))
func setupGame() {
score = 0
physicsWorld.gravity = CGVectorMake(5, 5)
}
func buttonPressed(sender: UIButton) {
}
playAgain.setTitle("Play Again", forState: UIControlState.Normal)
playAgain.titleLabel!.font = UIFont(name: "Helvetica", size: 50)
playAgain.addTarget(self, action: "buttonPressed:", forControlEvents: .TouchUpInside)
playAgain.tag = 1
self.view!.addSubview(playAgain)
If you want to use your storyboard you should add a button and then drag into your code (Outlet). Check this link of how to create an outlet connection.
Or you could create a button programmatically as you have done and call setupGame.
playAgain.addTarget(self, action: "setupGame", forControlEvents: .TouchUpInside)
Simply replace "buttonPressed:" with "setupGame", and remove the buttonPressed function altogether.
You should make a IBAction instead of
func buttonPressed(sender: UIButton) {
}
but yes this is where the setupGame() function should be called
iBAction buttonPressed(sender:UIButton) {
setupGame()
}
and then just make sure you hook up your button to this function so it can detect the tapped interaction.
To call a function when a button is pressed, you should use UIButton.addTarget, which it looks like you already have. The problem is that you have the wrong action specified.
playAgain.addTarget(
self,
action: "buttonPressed:", // This should be "setupGame"
forControlEvents: .TouchUpInside
)
The action parameter of the .addTarget function essentially points to the function that should be called. The little colon after the name is to indicate that the function should accept the sender of the action as an argument.
Assuming this is being added to a button, helloWorld: corresponds to func helloWorld(sender: UIButton), and helloWorld (notice the missing colon) corresponds to func helloWorld()
So, you should use
func setupGame() {
score = 0
physicsWorld.gravity = CGVectorMake(5, 5)
}
//button code
// Notice how the function above has no arguments,
// so there is no colon in the action parameter of
// this call
playAgain.addTarget(
self, // the function to be called is in this class instance (self)
action: "setupGame", // corresponds to the above setupGame function
forControlEvents: .TouchUpInside
)
//other code
Related
When setting the action with the "addTarget" method on a button in Swift, is there a way for me to pass a parameter to the function I want to trigger?
Say I had a simple scenario like this:
let button = UIButton()
button.addTarget(self, action: #selector(didPressButton), for: .touchUpInside)
#objc func didPressButton() {
// do something
}
Obviously the above code works fine, but say I wanted the 'didPressButton' function to take in a parameter:
#objc func didPressButton(myParam: String) {
// do something with myParam
}
Is there a way I can pass a parameter into the function in the 'addTarget' method?
Something like this:
let button = UIButton()
button.addTarget(self, action: #selector(didPressButton(myParam: "Test")), for: .touchUpInside)
#objc func didPressButton(myParam: String) {
// do something with myParam
}
I'm coming from a JavaScript background and in JavaScript it's pretty simple to achieve this behavior by simply passing an anonymous function that would then call the 'didPressButton' function. However, I can't quite figure how to achieve this with swift. Can a similar technique be used by using a closure? Or does the '#selector' keyword prevent me from doing something like that?
Thank you to anyone who can help!
The short answer is no.
The target selector mechanism only sends the target in the parameters. If the string was a part of a subclass of UIbutton then you could grab it from there.
class SomeButton: UIButton {
var someString: String
}
#objc func didPressButton(_ button: SomeButton) {
// use button.someString
}
It is not possible to do that in iOS. You can get the View in the selector in your case it is a button.
button.addTarget(self, action: #selector(buttonClick(_:)), for: .touchUpInside)
#objc func buttonClick(_ view: UIButton) {
switch view.titleLabel?.text {
case "Button":
break
default:
break
}
}
This question already has an answer here:
Why does Xcode line-out autocomplete methods for selector?
(1 answer)
Closed 2 years ago.
I have a UIButton within a UITableViewCell. When I call addTarget on the button and attempt to put a function in, the autocomplete has the function crossed out with a white line (see first image). Xcode still allows me to put the function in and run the app; however, when the button is tapped the function isn't called.
Button initialization:
private let infoButton: UIButton = {
let button = UIButton()
button.backgroundColor = .clear
button.adjustsImageWhenHighlighted = false
button.setImage(Images.sizeGuide, for: .normal)
button.addTarget(self, action: #selector(infoButtonPressed(_:)), for: .touchUpInside)
return button
}()
Function (infoButtonPressed):
#objc private func infoButtonPressed(_ sender: UIButton) {
print("Button Pressed")
}
Because I reuse this cell multiple times and only one of these cells needs to have this button, I have a variable that dictates whether or not to show the button:
var hasInfoButton: Bool = false {
didSet {
if hasInfoButton {
setupInfoButton()
}
}
}
The function that is called above simply sets up the button using autoLayout. Something to mention: when I tried calling addTarget in this function, the app crashed with Unrecognized selector sent to instance...
The tableView in which this is embedded in is only static and displays data. Therefore, allowSelection and allowsMultipleSelection are both set to false.
Does anyone have a solution to this?
You shouldn't need (_ sender: UIButton) the method should just be:
#objc func infoButtonPressed() {
print("button pressed")
}
EDIT:
The button initializer is also a little strange. The way I generally go about this kind of thing is like this:
let button = UIButton()
private func configureButton() {
button.backgroundColor = .clear
button.adjustsImageWhenHighlighted = false
button.setImage(Images.sizeGuide, for: .normal)
button.addTarget(self, action: #selector(infoButtonPressed(_:)), for: .touchUpInside)
}
Then call configureButton() in viewDidLoad()
Can I add multiple target actions on a UIButton for the same event like below?
[button addTarget:self action:#selector(xxx) forControlEvents:UIControlEventTouchUpInside];
[button addTarget:object action:#selector(yyy) forControlEvents:UIControlEventTouchUpInside];
I made a quick app to test it out and it carries out both the actions on button press.
I want to know if it's good practice to do so, and also will the order of execution always remain the same?
Thanks in advance.
Edit: I did find this post which states it's called in reverse order of addition, i.e., the most recently added target is called first. But it's not confirmed
Yes it is possible to add multiple actions to a button.
personally i would prefer a Delegate to subscribe to the button.
Let the object you want to add as target subscribe on the delegate's method so it can receive events when you press the button.
or
A single action that forwards the event to other methods to be fully in control
A simple test in swift
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let button = UIButton(frame: CGRect(x: 50, y: 50, width: 300, height: 30))
button.backgroundColor = .orange
button.addTarget(self, action: #selector(action1), for: .touchUpInside)
button.addTarget(self, action: #selector(action2), for: .touchUpInside)
button.addTarget(self, action: #selector(actionHandler), for: .touchUpInside)
self.view.addSubview(button)
}
#objc func actionHandler(_ sender: UIButton){
print("actionHandler")
action1(sender)
action2(sender)
}
#objc func action1(_ sender: UIButton) {
print("action1")
}
#objc func action2(_ sender: UIButton) {
print("action2 \n")
}
}
Output after one click:
action1
action2
actionHandler
action1
action2
Can you confirm on the order of execution when normally adding the actions
Yes it is executed in the order you set the targets.
please anyone tell me, How to send additional parameter in addtarget function in swift 2.2?
Example:
button.addTarget(self, action: #selector(classname.myFunc(_:)), forControlEvents: UIControlEvents.TouchUpInside))
func myFunc(sender:UIButton){
print(“i am here“)
}
to
func myFunc(sender:UIButton,parameter:String){
print(“i am here“)
}
You can create a subclass of UIButton, add one property named parameter which you want to pass as an extra parameter.
In addTarget(), you can only choose passing the caller or not. In this case, the caller is a UIButton.
So use the subclass and call addTarget(), then you can get the string which you want send:
func myFunc(sender: customUIButton) {
// do something with sender.parameter
}
Hope it can help you.
In Swift 2.2 you can do something like this.
myUISlider.addTarget(self, action:#selector(self.onSliderValChanged(_:withEvent:)), forControlEvents: .ValueChanged)
func onSliderValChanged(slider: UISlider, withEvent event: UIEvent?) {
}
I use sender properties to send some parameters with it like
button.accessibilityHint = "param 1"
button.accessibilityValue = "param 2"
button.tag = 0
button.addTarget(self, action: #selector(buttonPressed(_:)), forControlEvents: UIControlEvents.TouchUpInside))
func myFunc(sender:UIButton){
print(sender.accessibilityHint) // param1
print(sender.accessibilityValue) // param2
print(sender.tag) // 0
}
It's not possible. You have to use a workaround.
button.addTarget(self, action: #selector(classname.myFunc(_:)), forControlEvents: UIControlEvents.TouchUpInside))
func myFunc(sender:UIButton){
self.myFunc2(sender, parameter: "My parameter")
}
func myFunc2(sender:UIButton,parameter:String){
}
Swift 5.0 code
theButton.addTarget(self, action: #selector(theFunc), for: .touchUpInside)
theButton.frame.name = "myParameter"
.
#objc func theFunc(sender:UIButton){
print(sender.frame.name)
}
EDIT
This is my current code with the programmed buttons.
override func viewDidLoad() {
super.viewDidLoad()
self.playVideo()
var filter = UIView()
filter.frame = self.view.frame
filter.backgroundColor = UIColor.orangeColor()
filter.alpha = 0.15
self.view.addSubview(filter)
// Do any additional setup after loading the view, typically from a nib.
//Add Images
var logoImage : UIImageView
logoImage = UIImageView(frame:CGRectMake(136, 50, 102, 104));
logoImage.image = UIImage(named:"patchicon.png")
self.view.addSubview(logoImage)
var textLogo : UIImageView
textLogo = UIImageView(frame:CGRectMake(51, 0, 273, 371));
textLogo.image = UIImage(named:"logopatch.png")
self.view.addSubview(textLogo)
//Add Buttons
let buttonLogin = UIButton.buttonWithType(.Custom) as! UIButton
buttonLogin.frame = CGRectMake(16, 519, 343, 60)
buttonLogin.layer.cornerRadius = 0.2 * buttonLogin.bounds.size.width
buttonLogin.addTarget(self, action: "buttonTouched", forControlEvents: UIControlEvents.TouchUpInside)
buttonLogin.setImage(UIImage(named:"loginButton.png"), forState: .Normal)
view.addSubview(buttonLogin)
let buttonRegister = UIButton.buttonWithType(.Custom) as! UIButton
buttonRegister.frame = CGRectMake(16, 587, 343, 60)
buttonRegister.layer.cornerRadius = 0.2 * buttonRegister.bounds.size.width
buttonRegister.addTarget(self, action: "buttonTouched2", forControlEvents: UIControlEvents.TouchUpInside)
buttonRegister.setImage(UIImage(named:"registerButton.png"), forState: .Normal)
view.addSubview(buttonRegister)
}
func buttonTouched()
{
performSegueWithIdentifier("loginTouched", sender: nil)
}
func buttonTouched2()
{
performSegueWithIdentifier("registerTouched", sender: nil)
}
This is what my Storyboard looks like:
http://i.stack.imgur.com/MlEhI.png
How can I program these buttons further to switch into new view controllers? For instance, I want to click the register button and I want the current MainViewController to switch to a new one that will have the information for the user to sign up and so forth...
Thanks!
First, you need to add a target to the button:
buttonLogin.addTarget(self, action: "buttonTouched", forControlEvents: UIControlEvents.TouchUpInside)
And then, add this function:
func buttonTouched()
{
println("touched")
}
To switch to a new view controller, take a look at this
Well, to switch to a "new" view controller, you need to first create that view controller in your storyboard. After that, do you see that line that links the main view controller to the other two? Click that line and go to "Attributes Inspector". In the identifier blank space, fill with whatever you want and then, in the button that you created programmatically, you need to set this:
performSegueWithIdentifier("whateverYouWant", sender: self)
Oh, and don't forget this step: select your main view controller, go to Editor > Embed In > Navigation Controller. If you don't do this, your application will crash.
Hope that helps!
EDIT: Try this:
Write some function like this outside the viewDidLoad method:
func segueToNextVC(sender: UIButton!) {
println("Button pressed, let's see what happens!")
performSegueWithIdentifier("whateverYouWant", sender: self)
}
Then, in your button in viewDidLoad, do like this:
buttonLogin.addTarget(self, action: "segueToNextVC:", forControlEvents: UIControlEvents.TouchUpInside)
Note: Don't forget the : in segueToNextVC:, that's important!
add target to your button..
buttonLogin.addTarget(self, action: "btnpressed:", forControlEvents: .TouchUpInside)
Vtwot is my Second viewController and its Storyboard Id is ViewTwoId..
make UIButtons action like these..
func btnpressed(sender: UIButton!)
{
let jj = self.storyboard!.instantiateViewControllerWithIdentifier("ViewTwoId") as! Vtwot
self.navigationController!.pushViewController(jj, animated: true)
}
i hope it helps..