NOTE: Others have asked a similar question and none of the answers provided solved my problem.
Here's my code:
#IBOutlet var testButton:UIButton!
override func viewDidLoad() {
self.testButton.setImage(UIImage(named: "icn_checkbox_")?.imageWithColor(color: CMStyle.darkBlueColor), for: .normal)
self.testButton.setImage(UIImage(named: "icn_checked")?.imageWithColor(color: CMStyle.darkBlueColor), for: .selected)
}
#IBAction func testButtonAction(_ sender: Any) {
print("INSIDE testButtonAction")
self.testButton.isSelected = !self.testButton.isSelected
print("self.testButton.isSelected: ",self.testButton.isSelected)
}
This is the button:
.
These are the characteristics of the button:
.
This is icn_checkbox_ image used for .normal state:
This is icn_checked image used for .selected state:
The code inside testButtonAction gets executed. So I don't really see why wouldn't the image change (Why doesn't the button become checked).
You can use this:
#IBOutlet var testButton: UIButton!
override func viewDidLoad() {
self.testButton.setImage(UIImage(named: "icn_checkbox_")?.imageWithColor(color: CMStyle.darkBlueColor), for: .normal)
}
#IBAction func testButtonAction(_ sender: Any) {
print("INSIDE testButtonAction")
self.testButton.isSelected = !self.testButton.isSelected
if self.testButton.isSelected {
self.testButton.setImage(UIImage(named: "icn_checked")?.imageWithColor(color: CMStyle.darkBlueColor), for: .normal)
} else {
self.testButton.setImage(UIImage(named: "icn_checkbox_")?.imageWithColor(color: CMStyle.darkBlueColor), for: .normal)
}
}
You can set images for button states just in Storyboard, where Default = .normal and Selected = .selected
Choose selected and set image there. Image with color is similar to tintColor if You're using template images
Related
I'm creating a test that has 5 buttons, each button corresponds to a specific color, the problem is that when I select a consecutive 2nd button, the previous button is still selected, how can I make my code select only one button at a time and deselect the previous one?
How can I fix this?
This is my code
class ViewController: UIViewController {
var buttonPressed: Bool = false
#IBOutlet weak var button1: UIButton!
#IBAction func buttonAction1(_ sender: UIButton) {
if buttonPressed {
buttonPressed = false
button1.setImage(UIImage(named: "Bolinha-5"), for: .normal)
}
else {
buttonPressed = true
button1.setImage(UIImage(named: "Bolinha-4"), for: .normal)
}
}
#IBOutlet weak var button2: UIButton!
#IBAction func buttonAction2(_ sender: UIButton) {
if buttonPressed {
buttonPressed = false
button2.setImage(UIImage(named: "Bolinha-5"), for: .normal)
}
else {
buttonPressed = true
button2.setImage(UIImage(named: "Bolinha-4"), for: .normal)
}
}
#IBOutlet weak var button3: UIButton!
#IBAction func buttonAction3(_ sender: UIButton) {
if buttonPressed {
buttonPressed = false
button3.setImage(UIImage(named: "Bolinha-2"), for: .normal)
}
else {
buttonPressed = true
button3.setImage(UIImage(named: "Bolinha-4"), for: .normal)
}
}
#IBOutlet weak var button4: UIButton!
#IBAction func buttonAction4(_ sender: UIButton) {
if buttonPressed {
buttonPressed = false
button4.setImage(UIImage(named: "Bolinha-3"), for: .normal)
}
else {
buttonPressed = true
button4.setImage(UIImage(named: "Bolinha-4"), for: .normal)
}
}
#IBOutlet weak var button5: UIButton!
#IBAction func buttonAction5(_ sender: UIButton) {
if buttonPressed {
buttonPressed = false
button5.setImage(UIImage(named: "Bolinha-3"), for: .normal)
}
else {
buttonPressed = true
button5.setImage(UIImage(named: "Bolinha-4"), for: .normal)
}
}
}
What you are going to accomplish is called Radio Buttons, unfortunately iOS (unlike macOS) doesn't provide this functionality.
My suggestion takes advantage of the option to assign different images to different states in Interface Builder – in this case the Default and Selected state – and to create an outlet collection, an array representing a sequence of UI elements of the same type.
The suggestion doesn't support an empty selection, by default the first button is selected.
In ViewController
create an outlet collection
#IBOutlet var buttons : [UIButton]!
and one IBAction
#IBAction func buttonAction(_ sender: UIButton) { }
In Interface Buider
set the images to the Default and Selected states of each button in the Attribute Inspector.
connect the buttons in the proper order to the outlet collection.
assign the tags 0 to 4 to the buttons in the same order.
connect all buttons also to the (same) IBAction.
In ViewController
create a property for the tag of the currently selected button
var selectedButton = 0
in viewDidLoad select the first button
override func viewDidLoad() {
super.viewDidLoad()
buttons[selectedButton].isSelected = true
}
Complete the IBAction, it deselects the previous button and selects the current.
#IBAction func buttonAction(_ sender: UIButton) {
let tag = sender.tag
buttons[selectedButton].isSelected = false
buttons[tag].isSelected = true
selectedButton = tag
}
let's consider you have named your buttons as follows: 1st button: "opt1Button", 2nd button: "opt2Button", 3rd button: "opt3Button" and so on...
create an IBAction with name "optionSelected" The function will look like:
#IBAction func optionSelected(_ sender: UIButton) {
opt1Button.isSelected = false
opt2Button.isSelected = false
opt3Button.isSelected = false
opt4Button.isSelected = false
opt5Button.isSelected = false
sender.isSelected = true
}
As soon any of the options is selected all the buttons will go to 'isSelected' false condition i.e all the buttons will be deselected at first and the selected button will be marked as selected. Same process will be followed again when any of the button is selected, everything will get deselected and the button user has pressed will be marked as selected.
Found this answer from (https://developer.apple.com/forums/thread/685124) and it worked for me.
I have a screen with a UIImage and a UIButton on it. I wrote code so that when the button is clicked the image changes and it worked. Then I wanted to add code to make the title of the button as well. After I added that code the program crashes with a sigabrt error. I checked the connections and everything look fine. How would I change the text/title of a button without having it crash.
class MapViewController: UIViewController {
#IBOutlet weak var mapButton: UIButton!
#IBOutlet weak var mapImage: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
//mapButton.setTitle("test", for: .normal)
// Do any additional setup after loading the view.
}
#IBAction func mapButtonTapped(_ sender: UIButton) {
if x == true
{
mapImage.image = #imageLiteral(resourceName: "map")
x = false
mapButton.setTitle("1st Floor Map", for: .normal)
}
else
{
mapImage.image = #imageLiteral(resourceName: "School Map 2015-2016-2")
mapButton.setTitle("2nd Floor Map", for: .normal)
x = true
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
var x:Bool = true;
Connection tab
In the mapButtonTapped(_ sender:), you can change
mapButton.setTitle("2nd Floor Map", for: .normal)
to
sender.setTitle("2nd Floor Map", for: .normal)
sender here is the button which you tapped, and you had chosen the type to UIButton, you can access its properties as UIBUtton.
About the sigabrt error, you should try here.
I have three buttons named One, Two, and Three, and a function buttonPressed for collection of those three buttons as follows.
var btnTag = [Int]()
#IBAction func buttonPressed(_ sender: UIButton) {
guard let button = sender as UIButton? else { return }
if(btnTag.contains((sender as AnyObject).tag!))
{
if let index = btnTag.index(of: (sender as AnyObject).tag!)
{
btnTag.remove(at: index)
}
}
else
{
btnTag.append((sender as AnyObject).tag!)
}
if !button.isSelected {
button.isSelected = true
button.setTitleColor(.red, for: .normal)
}
else
{
button.isSelected = false
button.setTitleColor(.white, for: .normal)
}
}
I like to change color of button as red when clicked and then when I click other button the previous button color as white. So if I press One, I want One to be red and then when I pres Two, I want Two to be red and One as white. I did the above but it is allowing multiple selection and not able to deselect previous changes. How do I solve this?
You can simply create collection of UIButton. After that assign tag of all three UIButton from Storyboard.
#IBOutlet var buttons: [UIButton]!
Use above collection and connect all the button with Outlet. also connect below action with all buttons.
#IBAction func buttonPressed(_ sender: UIButton) {
buttons.forEach { $0.isSelected = false
$0.setTitleColor(.white, for: .normal)
}
buttons[sender.tag].setTitleColor(.red, for: .normal)
buttons[sender.tag].isSelected = true
}
Since you are highlighting only one button at the moment, you don't need tag array instead the reference to all buttons.
//Let say these are my button refrence
#IBOutlet weak var button1: UIButton!
#IBOutlet weak var button2: UIButton!
#IBOutlet weak var button3: UIButton!
All of those buttons are targeting same method
#IBAction func buttonPressed(_ sender: UIButton) {
//clear all button selected state
clearSelectedState()
//select the button that was clicked
sender.isSelected = true
sender.setTitleColor(.red, for: .normal)
}
func clearSelectedState() {
button1.isSelected = false
button1.setTitleColor(.white, for: .normal)
.... proceed to do for others
}
Now in clearSelectedState method I don't like the repetition of code. So what we can do is put the reference in array and do something like
///this can be replaced in clear state method
[button1, button2, button3,...].forEach {
$0.isSelected = false
$0.setTitleColor(.white, for: .normal)
}
Here I had placed two radio buttons on view controller class but unable to give logic to make a radio button active at a time can anyone help me ?
#IBAction func radioButtonAction(_ sender: KGRadioButton) {
sender.isSelected = !sender.isSelected
if sender.isSelected {
workRadioButton.isSelected = false
} else{
}
}
#IBAction func WorkRadiobuttonAction(_ sender: KGRadioButton) {
sender.isSelected = !sender.isSelected
if sender.isSelected {
homeRadioButton.isSelected = false
} else{
}
}
I am just using UIButton as radioButton.try like below
Create one array to store radio buttons
var radioButtonArray = [UIButton]()
Declare your radio buttons as UIButton or anyOther
#IBOutlet weak var radioButton1: UIButton!
#IBOutlet weak var radioButton2: UIButton!
Append all buttons into array
radioButtonArray.append(contentsOf: [radio1,radio2])
Set same target for all buttons
self.radioButton1.addTarget(self, action: #selector(self.folderRadioButtonClicked(_:)), for: UIControlEvents.touchUpInside)
self.radioButton2.addTarget(self, action: #selector(self.folderRadioButtonClicked(_:)), for: UIControlEvents.touchUpInside)
func folderRadioButtonClicked(_ sender:UIButton) {
for i in 0..<self.radioButtonArray.count {
if self.radioButtonArray[i] == sender{
// here you can perform what you want
self.radioButtonArray[i].setImage(UIImage(named: "checked.png"), for: UIControlState())
}else {
self.radioButtonArray[i].setImage(UIImage(named: "unchecked.png"), for: UIControlState())
}
}
}
I have multiple checkboxes that work decently.
The way it works is that there's two images (an image of a checked box OR an image of an unchecked box) that show up or disappear into my button, based on clicking that button.
For some reason when it's the first time I click a checkbox it works perfectly (changes its state to: checked or unchecked - when clicked once), but when i go to try a second, third, or fourth (etc.) checkbox, it requires two clicks to change its state (checked/unchecked).
This is annoying and confusing to the user. Is there any way around this?
Here are my last 3 checkboxes:
/////Checkboxes
#IBOutlet weak var Box49: UIButton!
#IBOutlet weak var Box50: UIButton!
#IBOutlet weak var Box51: UIButton!
var BoxON = UIImage(named: "CheckBox")
var BoxOFF = UIImage(named:"UnCheckBox")
var isBoxClicked: Bool!
override func viewDidLoad() {
super.viewDidLoad()
isBoxClicked = false
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func Box49(_ sender: Any) {
if isBoxClicked == true{
isBoxClicked = false
}else{
isBoxClicked = true
}
if isBoxClicked == true{
Box49.setImage(BoxON, for: UIControlState.normal)
}else{
Box49.setImage(BoxOFF, for: UIControlState.normal)
}
}
#IBAction func Box50(_ sender: Any) {
if isBoxClicked == true{
isBoxClicked = false
}else{
isBoxClicked = true
}
if isBoxClicked == true{
Box50.setImage(BoxON, for: UIControlState.normal)
}else{
Box50.setImage(BoxOFF, for: UIControlState.normal)
}
}
#IBAction func Box51(_ sender: Any) {
if isBoxClicked == true{
isBoxClicked = false
}else{
isBoxClicked = true
}
if isBoxClicked == true{
Box51.setImage(BoxON, for: UIControlState.normal)
}else{
Box51.setImage(BoxOFF, for: UIControlState.normal)
}
}
Thanks, Dan
The issue you are using same instance property isBoxClicked with all button instead of that you need to set the image to all button for both state normal and selected and then in your button action simply changed its selected state.
Also either change your button outlet name or action name because they both are same. So it should be like this.
#IBOutlet var box49: UIButton!
#IBOutlet var box50: UIButton!
#IBOutlet var box51: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
box49.setImage(BoxOFF, for: .normal)
box49.setImage(BoxON, for: .selected)
box50.setImage(BoxOFF, for: .normal)
box50.setImage(BoxON, for: .selected)
box51.setImage(BoxOFF, for: .normal)
box51.setImage(BoxON, for: .selected)
}
And now set your button action this way.
#IBAction func box49Button(_ sender: Button) {
sender.isSelected = !sender.isSelected
}
#IBAction func box50Button(_ sender: Button) {
sender.isSelected = !sender.isSelected
}
#IBAction func box51Button(_ sender: Button) {
sender.isSelected = !sender.isSelected
}
Or you can add single button action and set that action to all three button instead of having three different action for each button like this.
#IBAction func boxButton(_ sender: Button) {
sender.isSelected = !sender.isSelected
}
you are using one instance of isBoxClicked variable for all button. You should create an array of isBoxClicked. by using array you can check further that which checkbox(UIButon) is check an which is unchecked .
var isBoxClickedArray:[int] = {0,0}
First create enum for get index of buttons
enum ButtonIndex{
case Box49
case Box50
}
assign enum value as tag in button
Box49Button.tag = ButtonIndex.Box49.rawValue
Box50Button.tag = ButtonIndex.Box50.rawValue
create one method for get action
#IBAction func actionType(_ sender: Any) {
let button = sender as! UIBarButton
if ( button.tag == ButtonIndex.BOX49.rawValue ){
print("Box49 button pressed")
if ( isBoxClicked[ButtonIndex.BOX49.rawValue] == 0 ){
print("box49 is unchecked")
isBoxClicked[ButtonIndex.BOX49.rawValue] = 1// change it's value to checked
// change image also
}else{
// box is checked
isBoxClicked[ButtonIndex.BOX49.rawValue] = 0
// change value in array and image also
}
}else{
print("Box50 button pressed")
}
}
update
declare array in viewcontroller. and assign tag on button in viewdidload or cellforrowAtindexpath if you are using tableview. for enum declare them like this
import UIKit
enum indexs : Int{
case first
case second
}
class ViewController: UIViewController {