I have an empty array, and I have #IBAction func test(_ sender: UIButton) with 25 different buttons attached to this func. how can I write the code for appending a button title to the array, when pressed?
someArray.append = (this part that I can't figure out?)
Since I don't know which button/buttons will be pressed I can't just write someArray.append = ("buttonTitle")
(ive googled and searched in here for hours, but I can't find the solution)
if let title = sender.title(for: sender.state) {
someArray.append(title)
}
For multiple UIButtons with single IBOutlet Action you can add tags for each UIButton.
So if you've used StoryBoard for UIButtons, so when you click on single UIButton - navigate to Attribute Inspector & add tag to each button. As shown in below fig.1.0
I've set all UIButtons with different title & tags.
Once you set tags, for all buttons, then programmatically you can identify which button is clicked via single - onClick function.
#IBAction func Click(_ sender: UIButton) {
if let title = sender.title(for: sender.state){
print(title)
//Here we are identifying which button is pressed. If I pressed UIButton.tag = 1 then I'm just printing it's title, else appending UIButton value in array.
if sender.tag == 1 {
print(sender.title(for: sender.state))
}
else{
self.someArray.append(title)
}
}
}
So, in this way you can identify all your UIButton actions within a single event action.
#IBOutlet weak var btnoutlet: UIButton!
if let title = btnoutlet.currentTitle {
someArray.append(title)
}
Related
I'm a beginner in swift, I'm making an app in storyboard UIKit, and I need some help basically I need to set up a view controller that has buttons on it that when clicked add a string on the bottom of the VC, and if clicked again it will remove that same string. On the VC there going to be multiple buttons like this for options also on the bottom of the VC I need the label to update during the app also it should display like this for example. "Football","Basketball","Golf". It needs to be displayed just like that on the bottom with quotes and commas. I've to turn to make action buttons with a global array and put that inside each button but I can't figure out how to remove it when the button clicked again, also if you click the button again it'll add the same thing again so in the array you'll have two of the same strings. Anything would help.
P.S I need to do this in UIkit and Storyboard
You can make list of outlets to an array UIButton, handle list of actions when click into UIButton with a function. Using 'isSelected' property of UIButton to distinguish 'delete' or not.
class ViewController: UIViewController {
#IBOutlet weak var descriptionLabel: UILabel!
#IBOutlet var allButtons: [UIButton]!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func didTapButton(_ sender: UIButton) {
sender.isSelected.toggle()
_updateDescription()
}
private
func _updateDescription() {
descriptionLabel.text = allButtons
.filter { $0.isSelected }
.compactMap { $0.titleLabel?.text }
.map { "\"\($0)\"" }
.joined(separator: ", ")
}
}
I have two UIButtons that I want to use to set an A/B value to a variable before I save data to a database. I want a button to become selected when tapped, and deselected when the other button is tapped, and vice versa. What is a good solution for accomplishing this programmatically or in Interface Builder?
In order to set an "A/B value" as you mention, the easiest option would be to use a UISwitch or -in the general case of possibly more than 2 options- a UISegmentedControl (as #rmaddy suggested in the question's comments) .
These controls have built-in the "choose just one out of many" functionality that you are looking for.
The drawbacks of the switch are:
It has to be either on or off (does not support a selection state of "neither A nor B")
You can't have separate title labels for each state.
If you still want two separate UIButton instances, you can:
Have references to both buttons in your view controller (#IBOutlets wired using Interface Builder), e.g.:
#IBOutlet weak var leftButton: UIButton!
#IBOutlet weak var rightButton: UIButton!
Implement the action method for both buttons in such a way that it sets the selected state of the tapped button, and resets the other one. For example:
#IBAction func buttonAction(sender: UIButton) {
if sender == leftButton {
leftButton.isSelected = true
rightButton.isSelected = false
} else if sender == rightButton{
leftButton.isSelected = false
rightButton.isSelected = true
}
}
This is a quick-and-dirty solution for just two buttons. If you want a generic radio group of n-buttons, there are open source solutions on GitHub, etc...
Try this.
First create both button separate #IBOutlet.
#IBOutlet weak var btnYes: UIButton!
#IBOutlet weak var btnNo: UIButton!
Set Both Button Tag Like this and you also set tag using storyboard.
override func viewDidLoad() {
super.viewDidLoad()
btnYes.tag = 1
btnNo.tag = 2
}
Implement Common #IBAction method for both buttons
#IBAction func btnYesNoTapped(_ sender: UIButton) {
if sender.tag == 1 {
self.IsBtnSelected(isSelect: true, with: self.btnYes)
}else {
self.IsBtnSelected(isSelect: true, with: self.btnNo)
}
}
Create Custome Method
func IsBtnSelected(isSelect:Bool,with sender:UIButton){
self.btnYes.isSelected = false
self.btnNo.isSelected = false
sender.isSelected = isSelect
}
you can use following function for creating a radio button behaviour, you have to btn outlet to be selected and array of both outlets to this function. instead ofcolor you can also compare images and set images. for getting a required value yo can create a variable in viewcontroller and assign this variable a value in IBAction of btn and you can call this function from IBAction.
func radioButton(_ btnToBeSelected: UIButton, _ btnArray: [UIButton]) {
for btn in btnArray {
if btn == btnToBeSelected {
btn.backgroundColor = UIColor.black
//selected btn
//You can also set btn images by
//btn.setImage(<#T##image: UIImage?##UIImage?#>, for: <#T##UIControlState#>)
} else {
btn.backgroundColor = UIColor.red
//not selected btn
}
}
}
In iOS , you would have to do it manually.See the below approaches,
Use a switch . Using a UISwitch would be better if the option indicates a on/off state.
Use a same method when the button is pressed. Whenever the method gets called deselect the other button/buttons and select the pressed button. You can use tags or keep a reference of the buttons to differentiate between them.
Lastly , keep different methods for each buttons . Just deselect the other buttons whenever the button is pressed.
You can follow the above approaches by using interface builder or programmatically.
You can achieve it like below
I have implemented it for dates which are in TableView you just need to do little modifications
enum filterDateSelectableOptions:Int {
case AssignDate
case DueDate
case CompletionDate
}
//Assign Date selected by default
var currentSelectedFilterDate:filterDateSelectableOptions = .AssignDate
Now
func btnRadioButtonTapped(sender:UIButton) {
switch sender.tag {
case kTableViewRow.AssignDate.rawValue:
self.currentSelectedFilterDate = .AssignDate
case kTableViewRow.DueDate.rawValue:
self.currentSelectedFilterDate = .DueDate
case kTableViewRow.CompletionDate.rawValue :
self.currentSelectedFilterDate = .CompletionDate
default:
break;
}
//sender.isSelected = !sender.isSelected
self.tblFilterList.reloadData()
}
in cellForRow I have
// THIS IS DIFFERENT ENUM SO +1 is required in my case
case .AssignDate,.DueDate,.CompletionDate :
let button = buttonRadioCircle
button.tag = row.rawValue
cell.accessoryView = button
button.addTarget(self, action: #selector(btnRadioButtonTapped(sender:)), for: .touchUpInside)
button.isSelected = self.currentSelectedFilterDate.rawValue + 1 == row.rawValue
}
I have a method which generates several buttons, all with the same properties. The buttons are arranged vertically, like that:
What I need is that when each of them is clicked, it is capable of recognizing if it is the first one from the top, or the second one etc., printing "I'am the first/second/etc one".
How can I do it considering that the method they have is the same?
If all you need is an integer, use the tag property in UIView.
If you have an array of buttons…
var buttons: [UIButton]
you could sort them by their position in their superview to determine their order:
var sortedButtons: [UIButton] {
return buttons.sorted(by: { $0.frame.origin.y < $1.frame.origin.y })
}
and then get the index of a button (and vice-versa):
func index(of button: UIButton) -> Int {
return sortedButtons.index(of: button)
}
func button(at index: Int) -> UIButton? {
guard index < buttons.count else { return nil }
return sortedButtons[index]
}
Then…
#IBAction func buttonClicked(_ sender: UIButton) {
guard let index = index(of: sender) else { return }
sender.setTitle("I am \(index)", for: .normal)
}
This would also work if you added your buttons to an Outlet Collection in a storyboard:
#IBoutlet var buttons: [UIButton]!
Quick and dirty approach:
When dragging the outlet for the button, for the connection type select "Outlet Collection". This will create an outlet "to" a button array. Then you can drag and drop the rest of your buttons to this array. The order you make the drag n drop will be the order of your buttons in the array.
Then you can easily access them by index.
Caution: Easily breakable if re-drag n dropping the collection.
I have three buttons,and only one button can be chosen by the user at a time,that means that other then the initial state where none are chosen only one button can be at a highlighted state at a time.After another button (a forth one) is clicked,all the previous button's abilities to be clicked on are disabled.How do I do this?
button.enabled = false /// this will make a button disabled in swift
Why not use the 4th button to toggle a bool - that can be used to check on the state of the other buttons?
var lockedButtons: Bool = true
#IBAction func toggleButtonLock(sender: UIButton) {
lockedButtons = !lockedButtons
}
#IBAction func Button1(sender: UIButton) {
if !lockedButtons{
//Button1 code
}
}
//button 2 & 3 code similar....
I am creating a post to twitter app and want to add various text to the UITextField from buttons that can be selected. The UIButton are for various hashtags to speed the process of writing a tweet. I have tried a couple the solutions found on Stack but none seem to work and they are all in Objective-C.
Screenshot of compose tweet view before buttons touched.
http://postimg.org/image/5qoyk6673/
Screenshot of compose tweet view after button selected and text added to text field.
http://postimg.org/image/vp08wsa6b/fa7c7a83/
class TweetComposeViewControler: UIViewController, UITextViewDelegate {
var selectedAccount : ACAccount!
#IBOutlet var tweetContent: UITextView!
#IBAction func specializedButton(sender: UIButton) {
tweetContent.text = sender as UIButton
tweetContent.text.stringByAppendingString(specializedButton(titleLabel.text))
}
func insertHashtag(sender: UIButton!) {
tweetContent.text = tweetContent.text.stringByAppendingString(sender.titleLabel.text)
}
You can set the UITextFields text to the title of your UIButton:
txtField.text = hashTagButton.titleLabel.text
And if you want to append the text:
txtField.text = textField.text.stringByAppendingString(hashTagButton.titleLabel.text)
In order to have your buttons update the text upon pressing them you need to add a target selector for when the buttons are pressed. This can be done via Storyboard or programmatically.
Programmatically
You would add the same selector to all buttons using this:
hashtagButton.addTarget(self, action: Selector("insertHashtag:"), forControlEvents: .TouchUpInside)
This will call the insertHashtag function whenever the hashtagButton is pressed. Because of the : at the end of the selector, it will also pass itself as a parameter so you can use it to get the button's title rather than creating a different selector for each button.
func insertHashtag(sender: UIButton!) {
txtField.text = textField.text.stringByAppendingString(sender.titleLabel!.text)
}
Using IBAction
#IBAction func insertHashtag(sender: AnyObject) {
txtField.text = sender as UIButton
textField.text.stringByAppendingString(btn.titleLabel!.text)
}
Here you cast the sender paramter as a UIButton since you know a UIButton is the type of the object which called it.
If you know that only UIButton's will cause this method you can do this:
#IBAction func insertHashtag(btn: UIButton ) {
txtField.text = sender as UIButton
textField.text.stringByAppendingString(btn.titleLabel!.text)
}
Response to your update
The code you added needs to be fixed to look like this:
#IBAction func specializedButton(sender: UIButton) {
tweetContent.text.stringByAppendingString(sender.titleLabel!.text)
}
Here sender is your UIButton and you pass it as a UIButton so you do not need to convert it.