I am trying to add button programmatically, I created button, it shows in app, but problem that when I write .addTarget in #selector occurs error (it builds successfully, but action do not work) I tried to write playAction() and playAction(sender:) and playAction. None of them work.
playPauseButton.addTarget(self, action: #selector(playAction(sender:)), for: .touchUpInside)
#objc
func playAction(sender: UIButton){
print("Hello")
}
UPD: I solved by creating just system button and changed it. Maybe my Xcode have bug and because of that occurs error.
Change with
playPauseButton.addTarget(self, action: #selector(playAction), for: .touchUpInside)
this is ok:
#objc
func playAction(sender: UIButton) {
print("Hello")
}
works for me
Your function needs to have the #objc attribute. This allows it to be looked-up as a selector.
#objc
func playAction(sender: UIButton) {
print("Hello")
}
Related
I am trying to execute two functions in another view by pressing two buttons. Each button should call one of the functions, that is passed on through delegation.
But it seems like when I am pressing one of the buttons they execute both functions of the protocol simultaneously.
Only when I comment/remove one function it works.
The protocol:
protocol ManipulateSectionDelegate {
func addSection()
func removeSection()
}
The MainView:
Here are the functions that should get called, when pressing the buttons in the second View
extension MainViewController: ManipulateSectionDelegate{
#objc func showSettingsView(){
let settingsController = SettingsViewController()
settingsController.delegateManipuplateSection = self
navigationController?.pushViewController(settingsController, animated: true)
}
func addSection(){
semesterList.append(Semester.init(subject: [], done: false))
subjectTableView.reloadData()
print(semesterList)
}
func removeSection(){
semesterList.removeLast()
subjectTableView.reloadData()
print(semesterList)
}
}
The second View:
class SettingsViewController:UIViewController{
var delegateManipuplateSection: ManipulateSectionDelegate?
override func viewDidLoad() {
super.viewDidLoad()
addSectionButton.addTarget(self, action: #selector(addSectionButtonPressed), for: .touchUpInside)
addSectionButton.addTarget(self, action: #selector(removeSectionButtonPressed), for: .touchUpInside)
}
}
extension SettingsViewController{
#objc func addSectionButtonPressed(){
delegateManipuplateSection?.addSection()
}
#objc func removeSectionButtonPressed(){
delegateManipuplateSection?.removeSection()
}
}
Even though each button is connected to a different function and should execute only one of them, both get executed.
Is this a situation where I would have to use observers and notifications? Did I do something wrong?
You connected two actions to one same button
addSectionButton.addTarget(self, action: #selector(addSectionButtonPressed), for: .touchUpInside)
addSectionButton.addTarget(self, action: #selector(removeSectionButtonPressed), for: .touchUpInside)
I am new to iOS app development using Swift 4. I used the code below to change the image of button2 by running it in the iOS simulator:
#IBAction func button2(_ sender: Any) {
button2.setImage(UIImage(named: "wrong_answer"), for: .normal)
}
However, button2 was highlighted when I first click on it without changing its image. Then after the second click, the image has been changed in button2.
My question is why the image was not changed in button2 after the first click?
What can I do to change the image after the first click instead of twice? Is this a bug in the iOS simulator of Xcode or it is normal?
You probably have an issue related to UIButton states that is causing this problem.
I don't think it is a simulator bug.
By the way, a good practice you should follow is to name the outlet different than the #IBAction. Let's say:
#IBAction func buttonTapped(_ sender: Any) {
button.setImage(UIImage(named: "image"), for: .normal)
}
Try this:
override func viewDidLoad() {
super.viewDidLoad()
button.setImage(UIImage(named: "image"), for: .selected)
}
#IBAction func buttonTapped(_ sender: Any) {
button.isSelected = !button.isSelected
}
And then the image will be updated automatically when you tap on the button. You can change it to button.isSelected = true if you want to keep the image after the first tap.
Rename your method/action so it differs from the button/property.
Change Any to UIButton since you know its class.
#IBAction func buttonTapped(_ buttonTapped: UIButton) {
buttonTapped. button.isSelected = !button.isSelected
}
Make sure that you are receiving the button callbacks by declaring your view controller a UIButtonDelegate and set the button's delegate property to self.
it's simulator bug. it worked on a real device
#IBAction func button2(_ sender: UIButton) {
button2.setImage(UIImage(named: "wrong_answer"), for: .normal)
}
I'd like to have a protocol:
protocol CameraButtonDelegate: class {
func cameraButtonDidPress(_ sender: UIButton)
}
So, I could assign any client to a button, e.g.:
cameraButton.addTarget(delegate, action: #selector(cameraButtonDidPress), for: .touchUpInside)
However, it does not compile as I have to specify a particular function in action, e.g.:
cameraButton.addTarget(delegate, action: #selector(AAPLViewController.cameraButtonDidPress), for: .touchUpInside)
How to solve this issue, if I'd like to have multiple clients being targeted by a single button?
It should work if you make the protocol #objc
#objc protocol CameraButtonDelegate: class {
func cameraButtonDidPress(_ sender: UIButton
}
and specify the selector as protocol method
cameraButtonDidPress.addTarget(delegate, action: #selector(CameraButtonDelegate.cameraButtonDidPress), for: .touchUpInside)
You can try
cameraButton.addTarget(Service.shared, action: #selector(Service.shared.cameraButtonDidPress(_:)), for: .touchUpInside)
//
class Service {
static let shared = Service()
#objc func cameraButtonDidPress (_ sender:UIButton){
}
}
How do I add a IBAction to a button programmatically?
button.addTarget(self, action: Selector(("buttonAction:")), for:
.touchUpInside)
func buttonAction(sender: Any) {
print("test")
}
That gives me an "Thread 1: signal SIGABRT" error.
Swift 4 version:
button.addTarget(self, action: #selector(action(sender:)), for: .touchUpInside)
#objc private func action(sender: Button) {
print("test")
}
I am trying to add a UITapGesture to a UIButton so it will trigger a function when tapped. I am using Swift 3 and is getting some error:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[SwiftRunner.ViewController tapBlurButton]: unrecognized selector sent to instance 0x149e07610'
This is roughly what I have:
// Swift 3
import UIKit
class ViewController {
#IBOutlet weak var qsBlurButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
let tapGesture = UITapGestureRecognizer(target: self, action: Selector(("tapBlurButton")))
qsBlurButton.addGestureRecognizer(tapGesture)
}
func tapBlurButton(sender: UITapGestureRecognizer) {
print("Please Help!")
}
}
From your code you are using swift 3.0 so change your selector syntax like this
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.tapBlurButton(_:)))
and Your function like this
func tapBlurButton(_ sender: UITapGestureRecognizer) {
print("Please Help!")
}
Edit:
Not idea that you are using button with tap gesture, instead of that use inbuilt method addTarget for button no need to create tap gesture for it like this
qsBlurButton.addTarget(self, action: #selector(self.tapBlurButton(_:)), forControlEvents: .TouchUpInside)
func tapBlurButton(_ sender: UIButton) {
print("Please Help!")
}
Swift 3
In the case where the func for the selector looks like this (note: it doesn't have a _):
func tapBlurButton(sender: UITapGestureRecognizer) {
print("Please Help!")
}
Then the selector looks like this:
#selector(self.tapBlurButton(sender:))
So the final code for the selector is this:
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.tapBlurButton(sender:)))
If you do not specify that the first parameter has _, then you need to use the full name of the first parameter.
To add a gesture recognizer you have to create one indicating which function it will call:
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.handleTapFrom(recognizer:)))
Then add it to the element you need. (You are using a button, and as others have explained buttons have their native 'addTarget' methods)
For explanation purposes imagine you want to add it to an UIView:
self.someView.addGestureRecognizer(tapGestureRecognizer)
And don't forget that some elements are "not user interactive" by default so you might have to change that property too:
self.someView.isUserInteractionEnabled = true
In Swift 4 the function needs the #objc declaration:
#objc func handleTapFrom(recognizer : UITapGestureRecognizer)
{
// Some code...
}