How to fix UIButton not responding to touch? - swift

I am working an app with quizzes, have 4 UIButtons (custom type) on subview which is custom view and none of the buttons is recognising the action even though I set the target. I have to do it programatically.
I have tried setting isUserInteractionEnabled but it is not working. Buttons are on the view, respecting the bounds.
Here, viewDidLoad from InitialViewController:
override func viewDidLoad()
{
super.viewDidLoad()
self.questionView?.firstanswer!.isEnabled = true
self.questionView?.firstanswer!.addTarget(self, action: #selector(self.answerTheQuestion), for: UIControl.Event.touchUpInside)
self.questionView?.secondanswer!.addTarget(self, action: #selector(self.answerTheQuestion), for: UIControl.Event.touchUpInside)
self.questionView?.thirdanswer!.addTarget(self, action: #selector(self.answerTheQuestion), for: UIControl.Event.touchUpInside)
self.questionView?.fourthanswer!.addTarget(self, action: #selector(self.answerTheQuestion), for: UIControl.Event.touchUpInside)
}
Here is the action function:
#objc func answerTheQuestion(_sender:UIButton) {
print("aa")
if let questionsAnswers = self.quizzes?.quizzes[self.randomNumber!]["questions"] as? [[String:Any]] {
if (questionsAnswers[self.randomQuestion!]["question"] as? String) != nil {
if let correctAnswer = questionsAnswers[self.randomQuestion!]["correct_answer"] as? String {
if _sender.titleLabel?.text == correctAnswer {
_sender.backgroundColor = UIColor.green
} else {
_sender.backgroundColor = UIColor.red
}
}
}
}
}
View and buttons are added normally, only tap is not working.
It should go red when the answer is wrong, and green when it is right. Questions and everything else is added normally, but it even won't print "aaa" in the beginning of the target function. Pls help, thanks!!

Related

Passing parameters in a clickable UIabel

I'm trying to make a clickable UILabel by following with this code:
let tap_plato = UITapGestureRecognizer(target: self, action: #selector(ViewController.ale_plato1))
plato1.isUserInteractionEnabled = true
plato1.addGestureRecognizer(tap_plato)
...
#objc
func ale_plato1(sender: UITapGestureRecognizer){
let label = sender.view
print ("tapped!")
}
This works well. But I want to pass parameters to the function. Something like this:
let tap_plato = UITapGestureRecognizer(target: self, action: #selector(MenuController.ale_plato1("parameter")))
plato1.isUserInteractionEnabled = true
plato1.addGestureRecognizer(tap_plato)
#objc
func ale_plato1(sender: UITapGestureRecognizer, parameterRecived: String){
}
But I don't know how do that in swift 3...
Any help? Thanks you
Wherever you make your multiple UILabel set each label to a different tag.
for i in 0..<3 {
let label = UILabel()
label.tag = i
let tap = UITapGestureRecognizer(target: self, action: #selector(tap))
label.isUserInteractionEnabled = true
label.addGestureRecognizer(tap_plato)
}
#objc func tap(sender: UITapGestureRecognizer) {
let label = sender.view as! UILabel // if you are SURE that your tap will be a UILabel
if(label.tag == 0) {
label.text = "This is label 0"
if(label.tag == 1) {
label.text = "This is label 1"
}
}
Threw this up in a jiffy, hop over the syntax issues if there are any.
Here we can create labels with tags and apply the same tap to them. From there, we can check what tag it is inside the tap method and do something from there.
You could use the tag attribute for Int values, but if you want anything other than that:
Create a custom UILabel Class with a value variable.
class LabelWithValue : UILabel {
var value : String = ""
}
Then you can use it as a normal Label
let label = LabelWithValue()
label.text = "bla"
label.value = "Anything"
label.isUserInteractionEnabled = true
label.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleGetText)))
Then you can get it's text and it's value.
#objc func handleGetText(_ sender : UITapGestureRecognizer) {
if let label = sender.view as? LabelWithValue {
print(label.text)
print(label.value)
}
}

How can I disable a button if an image has not been edited?

I want to try to disable a post button until an image has been chosen by the user.
However, I have a default image set as a placeholder.I have already managed to disable the post button when a textfield has not filled with information. I haven't, however, found a way to disable the button immediately.Hopefully I have explained myself.
Here's an image of my uiview
func handleBlancInformation(){
address.addTarget(self, action: #selector(PostViewController.textFieldDidChange), for: UIControlEvents.editingChanged)
breed.addTarget(self, action: #selector(PostViewController.textFieldDidChange), for: UIControlEvents.editingChanged)
phone.addTarget(self, action: #selector(PostViewController.textFieldDidChange), for: UIControlEvents.editingChanged)
}
#objc func textFieldDidChange() {
guard let address = address.text, !address.isEmpty,
let breed = breed.text, !breed.isEmpty,
let phone = phone.text, !phone.isEmpty,
let image = imagePosted.image, !imagePosted.isEqual("placeholder.png")
else {
postButton.setTitleColor(UIColor.lightText, for: UIControlState.normal)
postButton.isEnabled = false
return
}
postButton.setTitleColor(UIColor.white, for: UIControlState.normal)
postButton.isEnabled = true
}
Try This. Use bool for status to check weather image is selected or not.
var isImageSelected = false
override func viewDidLoad() {
postButton.isEnabled = false
}
Check Image is Selected or not. Change Button Enable property while selected image.
if isImageSelected{
// Do Your Work
}
I would need more code to give an exact solution here, but think about it this way:
Whatever method you are using for the user to choose a new image, that is where you should be enabling the "post" button.
For example, assuming you are using a UIImagePickerViewController to handle picking an image, you will want to enable the "post" button inside of this method, which is part of the UIImagePickerControllerDelegate:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
//Enable button here
} else {
//Disable button here
}
}
From what I understand the user can click when the View is loaded and you want to prevent this right?
but when they first enter the uiview they can click the post button
If so simply disable the button on the viewDidLoad() or in the storyboard.
override func viewDidLoad() {
postButton.isEnabled = false
}
or uncheck the "Enabled" field
To verify if an user did pick an image (after the View has loaded) check Greg's answer
This is how I managed to make the button dissapear from the moment the user enters this tab and show it once both the uiimage and the textfields have been filled out.
override func viewDidLoad() {
handleBlancInformation()
postButton.isHidden = true
}
func handleBlancInformation(){
address.addTarget(self, action: #selector(PostViewController.textFieldDidChange), for: UIControlEvents.editingChanged)
breed.addTarget(self, action: #selector(PostViewController.textFieldDidChange), for: UIControlEvents.editingChanged)
phone.addTarget(self, action: #selector(PostViewController.textFieldDidChange), for: UIControlEvents.editingChanged)
changeImageLostButton.addTarget(self, action: #selector(PostViewController.textFieldDidChange), for: UIControlEvents.editingChanged )
}
#objc func textFieldDidChange() {
guard let address = address.text, !address.isEmpty,
let breed = breed.text, !breed.isEmpty,
let phone = phone.text, !phone.isEmpty
else {
postButton.isHidden = true
return
}
postButton.isHidden = false
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any])
{
print("did Finish Picking Media")
if let image = info["UIImagePickerControllerOriginalImage"] as? UIImage {
selectedImage = image
imagePosted.image = image
}
else {
postButton.isHidden = true
}
self.dismiss(animated: true, completion: {
self.handleBlancInformation()
})
}

I want to use bool on button, if i click on button image of imageview changed and if again click on button then image reverse using Swift

my code is:
func PickUpCarCost() {
imgCheck.image = UIImage(named: "uncheck.png")
imgUnCheck.image = UIImage(named: "uncheck.png")
if CarPickUpButton?.tag == 1 {
imgCheck.image = UIImage(named: "check.png")
self.pickupChargelabel.text=self.PickUpFare.text!
}
else {
imgUnCheck.image = UIImage(named: "uncheck.png")
}
}
in this i wants take bool like if button selectes image view image will be check.png if unselect image view image will be uncheck.png how to code for this in swift.
You can you isSelected variable. And add different image for button state.
imgCheck.setImage(UIImage(named: "uncheck.png"), for: .selected)
imgCheck.setImage(UIImage(named: "check.png"), for: .normal)
Add UITapGestureRecognizer on your button like this. or you can use UIButton own property isSelected ?
#IBOutlet weak var myBtn: UIButton!
In your Viewdidload method add these line
let tapGesture = UITapGestureRecognizer(target: self, action: "handleTap")
myBtn.addGestureRecognizer(tapGesture)
func handleTap(sender: UITapGestureRecognizer) {
if sender.state == .ended {
// handling code
}
else if sender.state == .began {
}
}
Add gesture according to your needs.I used long tap and tap gesture
This code worked for me. Globally define var isclick = false
func CarDeliverCost() {
if (!isclick){
imgUnCheck.image = UIImage(named: "check.png")
isclick=true
}
else
{
imgUnCheck.image = UIImage(named: "uncheck.png")
isclick=false
}
}

Custom class to create an Alert with Buttons. How to add a completition handler?

I was trying to create a custom alert and I am getting mad trying to implement a completition handler on the buttons. I have tried a few things, the last, create func array to pass in the selector addTarget function of the UIButton, but not working. (where the ****** are)
The issue: "Argument of #selector does no refer to #obc method, property or initializer"
The difficult coding part I can't do is to configure the selector with some code I receive from my view controller where I create an object with the class below.
class Alert: NSObject {
func showAlert(){
if let window = UIApplication.shared.keyWindow {
//configure some constraints and animations
}
var buttons: [UIButton] = []
var buttonsFunc: [() -> Void ] = []
func addNewButton(title: String, handler: #escaping () -> Void) {
buttons.append(createButton(title: title))
buttonsFunc.append {
self.dismissAlert()
handler()
}
}
func setupButtons() {
for (index, button) in buttons.enumerated() {
boxView.addSubview(button)
//Here is the problem ***************************
button.addTarget(self, action: #selector(buttonsFunc[index]), for: .touchUpInside)
//More constraints(not important)
button.centerXAnchor.constraint(equalTo: boxView.centerXAnchor).isActive = true
button.widthAnchor.constraint(equalTo: (button.titleLabel?.widthAnchor)!).isActive = true
button.heightAnchor.constraint(equalToConstant: 25).isActive = true
}
}
func dismissAlert(){
//Animation to dismiss my alert
}
Other functions:
//Even if its not important the function i use to create the button
func createButton(title: String) -> UIButton {
let button = UIButton(type: .system)
button.backgroundColor = .clear
button.setTitle(title, for: .normal)
button.titleLabel?.sizeToFit()
button.setTitleColor(uPBlue, for: .normal)
button.titleLabel?.font = UIFont(name: uPFont, size: 20)
button.translatesAutoresizingMaskIntoConstraints = false
return button
}
Any ideas how to fix this?
Or maybe a totally different way.
If it works i take it.
So a selector is just the name of a function. A closure by definition is an anonymous function so you can't quite do it this way.
Lets try another route, define a new function to give to the buttons:
private func buttonPressed(sender: UIButton) {
}
Then lets give the buttons this function instead of the closure:
...
button.addTarget(self, action: #selector(Alert.buttonPressed(sender:)), for: .touchUpInside)
...
Now we can take advantage of tuples here. Instead of having two separate arrays we'll to one array with an adhoc data structure for our buttons:actions:
// var buttons: [UIButton] = []
// var buttonsFunc: [() -> Void ] = []
// Becomes
var buttonActionArray: [(button: UIButton, action: () -> Void)] = []
Now lets implement buttonPressed(sender:)
private func buttonPressed(sender: UIButton) {
for buttonTuple in buttonActionArray {
if buttonTuple.button === sender {
buttonTuple.action()
}
}
}

Implement checkbox in Swift

I am trying to implement a checkbox in Swift. I used the answer of an other post to get started.
First I created a button in the storyboard and gave it the class checkbox. After that I, created the class checkbox. It is currently looking like that. I had do make some adjustments from the other post, because he was using a different version of swift.
class checkbox: UIButton {
//Images
let checkedImage = UIImage(named: "selected")! as UIImage
let uncheckedImage = UIImage(named: "rectangle")! as UIImage
// Bool property
var isChecked: Bool = false {
didSet{
if isChecked == true {
self.setImage(checkedImage, for: .normal)
} else {
self.setImage(uncheckedImage, for: .normal)
}
}
}
func buttonClicked(sender: UIButton) {
if (sender == self) {
if self.isChecked == true
{
self.isChecked = false
}
else
{
self.isChecked = true
}
}
}
override func awakeFromNib() {
self.addTarget(self, action: Selector(("buttonClicked:")),for:UIControlEvents.touchUpInside)
self.isChecked = false
}
}
But now, I always get the following error in the AppDelegate, when I click the checkbox.
terminating with uncaught exception of type NSException
try this -
class CheckBoxButton: UIButton {
override func awakeFromNib() {
self.setImage(UIImage(named:"selected"), for: .selected)
self.setImage(UIImage(named:"rectangle"), for: .normal)
self.addTarget(self, action: #selector(CheckBoxButton.buttonClicked(_:)), for: .touchUpInside)
}
func buttonClicked(_ sender: UIButton) {
self.isSelected = !self.isSelected
}
}
I also recently had to make a checkbox and I used a cocoapod for that, instead of making my own. It lets you choose everything including colors, animations, shape and size! Maybe that helps:
BEM CHECKBOX
It really only takes 5 min to install and have it working on your app.
Safest way to make check box:
Add a UIButton to ViewController
Add two images to Project: 1.checked.png, 2.un-checked.png
Set checked or un-checked image as button background or button image
Set button text to ""
believe me, that libraries will make you confused.