Implement checkbox in Swift - 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.

Related

How to fix UIButton not responding to touch?

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

UIButton collection set color for last pressed button

I have an array of buttons which will act like a selector menu. I want that when I press one of them, it changes its backgroundColor and all the other buttons go back to their initial color.
This is what I have at the moment
#IBAction func optionSelected(_ sender: UIButton) {
for button in selectButtons {
if button.tag == sender.tag {
if !button.isSelected {
button.backgroundColor = palette.importantColorObject()
button.isSelected = true
} else {
button.backgroundColor = palette.clearGrayColorObject()
button.isSelected = false
}
}
}
But I don't know how to make that only the last selected button have this importantColorObject and I'm also having the problem that when I select the button, not only its background color changes, but it looks also like if text inside was being selected (in blue). How can I solve this?
Thanks in advance
This will solve your only one selection problem, this will make sure that you always have a selected button, unless you to deselect selected one and all your button go to gray or not selected state.
#IBAction func optionSelected(_ sender: UIButton) {
selectButtons.forEach { (button) in
button.backgroundColor = palette.clearGrayColorObject()
button.isSelected = false
}
sender.backgroundColor = palette.importantColorObject()
sender.isSelected = true
}
if you want that functionality too use this one
#IBAction func optionSelected(_ sender: UIButton) {
if sender.isSelected {
sender.backgroundColor = palette.clearGrayColorObject()
sender.isSelected = false
} else {
selectButtons.forEach { (button) in
button.backgroundColor = palette.clearGrayColorObject()
button.isSelected = false
}
sender.backgroundColor = palette.importantColorObject()
sender.isSelected = true
}
}
Hope this will help.

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