I have several buttons with titles 0 - 9 and in my custom UIButton class I want to be able to use a switch to check the button title. The buttons are created in the storyboard. The UIButton class looks like:
protocol NumpadDelegate: class {
func changeValue()
}
class NumpadButton: UIButton, NumpadDelegate {
let initial = String() // I want to assign the title of the button here
var alternative = String()
var change: Bool = false {
didSet {
let title = change ? alternative : initial
setTitle(title, forState: .Normal)
}
}
func changeValue() {
change = !change
}
}
Is there a way to do that or I'll have to programmatically create the buttons? I'm trying to limit the use of a custom UIButton class so I don't have to create one for each of my buttons.
EDIT:
As requested, the code of when the button is pressed:
#IBAction func buttonNumber(sender: UIButton) {
let value = sender.titleLabel!.text!
switch value {
case "C": orderLabel.text = ""
default: orderLabel.text = orderLabel.text.map { count($0) < 10 ? $0 + value : $0 } ?? value
}
if let check = orderLabel.text {
inputResult.removeAll(keepCapacity: false)
for index in 0..<items.count {
let id = items[index].id
if id.lowercaseString.hasPrefix(check.lowercaseString) {
inputResult += [items[index]]
}
}
numpadTableView.reloadData()
}
}
What I'm trying to do is, when I swipe the buttons I want their titles to change to an alternative String i.e. button with title 1 will change to A and button with title 2 will change to B.
Instead of assigning your buttons to a 'referencing outlet' in Interface Builder, assign them to a 'referencing outlet collection' which you can declare as
#IBOutlet var buttons: [NumpadButton]
Don't know exactly what you're going for but here's an example where I've created outlets for each NumpadButton and added them to an array.
class ViewController: UIViewController {
#IBOutlet weak var button1: NumpadButton!
#IBOutlet weak var button2: NumpadButton!
#IBOutlet weak var button3: NumpadButton!
#IBOutlet weak var button4: NumpadButton!
var array: NSMutableArray = []
override func viewDidLoad() {
super.viewDidLoad()
array.addObject(button1)
array.addObject(button2)
array.addObject(button3)
array.addObject(button4)
}
Each button has a title of either "1", "2", "3" or "4". Then you can check the title via a case statement like so:
override func viewWillAppear(animated: Bool) {
for item in array {
var button = item as! UIButton
switch button.currentTitle! {
case "1":
println("This button has title of 1")
case "2":
println("This button has title of 2")
case "3":
println("This button has title of 3")
case "4":
println("This button has title of 4")
default:
println("default case")
}
}
}
}
This would be one way you could use a case statement to access the titles of UIButtons and then just adjust the application to whatever functionality you want (e.g. through an IBAction, etc.).
Related
I have two IBAction groups with three buttons each.
Each button has a different tag - within each group: 1, 2 and 3.
I have three arrays, with three values each.
I want to press the first button of the first IBAction and change the title of the three buttons in the second IBAction, based on the group of arrays.
Here is the code:
import UIKit
class ViewController: UIViewController {
var firstArray = ["A1","A2","A3"]
var secondArray = ["B1","B2","B3"]
var thirdArray = ["C1","C2","C3"]
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func greenButtons(_ sender: UIButton) {
if sender.tag == 1 {
//change the title of the grayButtons with the firstArray
}
if sender.tag == 2 {
//change the title of the grayButtons with the secondArray
}
if sender.tag == 3 {
//change the title of the grayButtons with the thirdArray
}
}
#IBAction func grayButtons(_ sender: UIButton) {
}
}
You can try
// create outlet group for each
#IBOutlet weak var greenButtons:[UIButton]!
#IBOutlet weak var grayButtons:[UIButton]!
Inside action of greenButtons
grayButtons.forEach { $0.setTitle(firstArray[$0.tag - 1],for:.normal) }
Instead of if check you can construct the array as
let allArr = [ ["A1","A2","A3"], ["B1","B2","B3"],["C1","C2","C3"]]
Then
grayButtons.forEach { $0.setTitle(allArr[sender.tag - 1][$0.tag - 1],for:.normal) }
Im developing in Swift and I am displaying one string from an array by clicking a button. However, after the array is empty and the last string of the array is displayed, I want the user to be unable to click on the button since there are no more strings to display and the array is empty. So far I have crafted code to where the button is disabled after the array is empty but it stays disabled even after I had more strings to the array (by clicking another button). Any help would be highly appreciated.
#IBOutlet weak var selectedChoice: UILabel!
#IBOutlet weak var field: UITextField!
var choices = [String]()
//first button that adds string to array
#IBAction func addToChoices(_ sender: Any) {
choices.append(field.text!)
print(choices)
print(choices.count)
}
//button that I want to disable once 'choices.isEmpty' but enable it again after more strings are added to 'choices'
#IBAction func shuffleTilExhuasted(_ sender: Any) {
let button = sender as? UIButton
let rand = Int(arc4random_uniform(UInt32(choices.count)))
selectedChoice.text = choices[rand]
choices.remove(at: rand)
switch choices.isEmpty {
case true:
button?.isEnabled = false
case false:
button?.isEnabled = true
}
Re enable it when add , create IBOutlet of the button
//first button that adds string to array
#IBAction func addToChoices(_ sender: Any) {
choices.append(field.text!)
self.btn.isEnabled = true
print(choices)
print(choices.count)
}
OR use didSet with the array
var choices:[String] = []
{
didSet {
self.btn.isEnabled = choices.isEmpty
}
}
I have been looking around the web and I am unable to find a solution for my problem. I want my "START" button text to change to "RESTART" once the game has ended. If any additional information is needed please let me know. Thanks, all help is appreciated. Below is my code.
class ViewController: UIViewController {
var gameOver = false
var stopFuncs = false
var gameTimer = Timer()
var counter = 10
var selected = "NONE"
var score = 0
var colour = "NONE"
#IBOutlet weak var colourLabel: UILabel!
let colourProvider = ColourProvider()
#IBOutlet weak var scoreLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
colour = colourProvider.randomColour()
print(colour)
colourLabel.text = colour
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBOutlet weak var counterLabel: UILabel!
func updateCounter() {
if counter >= 0 {
counterLabel.text = String(counter)
counter -= 1
}
}
#IBAction func startButton() {
gameOver = false
counter = 10
stopFuncs = false
var _ = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(updateCounter), userInfo: nil, repeats: true)
}
#IBAction func greenButton() {
if stopFuncs { return }
compareColours(selectedColour: "GREEN")
changeColourLabel()
colourLabel.textColor = UIColor.green
}
#IBAction func blueButton() {
if stopFuncs { return }
compareColours(selectedColour: "BLUE")
changeColourLabel()
colourLabel.textColor = UIColor.blue
}
#IBAction func yellowButton() {
if stopFuncs { return }
compareColours(selectedColour: "YELLOW")
changeColourLabel()
colourLabel.textColor = UIColor.yellow
}
#IBAction func pinkButton() {
if stopFuncs { return }
compareColours(selectedColour: "GREEN")
changeColourLabel()
colourLabel.textColor = UIColor.red
}
func compareColours(selectedColour: String) {
if gameOver == false && counter >= 1 {
if selectedColour == colour {
score += 1
let scoreString = String(score)
scoreLabel.text = scoreString
}
else {
gameOver = true
}
}
else {
stopFuncs = true
}
}
func changeColourLabel() {
colour = colourProvider.randomColour()
colourLabel.text = colour
print(colour)
}
}
You already have IBOutlets to some of your labels.
For buttons you may need to set up both an IBaction and an IBOutlet.
An IBOutlet is a thing. A noun. It's a reference to a view object.
An IBAction is a verb. An action. It's code that gets called when something happens to a UIControl (tapping a button, moving a slider, changing the selected value on a segmented control, etc.)
The IBaction is a function that gets called when the user interacts with a control (For buttons you almost always link the action to the .touchUpInside control event.)
Naming your actions with names like pinkButton is a bad idea, and leads to confusion. I suggest renaming your actions to verbs, like handlePinkButton (or perhaps "pinkButtonTapped", but I prefer action names to be verbs.)
Note that when you rename an IBAction and/or IBOutlet you have to go into IB (IB = Interface Builder), select the connections inspector, remove the now-incorrect IBOutlet/IBAction and control-drag from the object to the updated outlet/action.
If you don't do that you'll get very confusing crashes at runtime:
Renaming IBOutlets in code without also changing them in IB gives the error "this class is not key value coding-compliant for the key old_outlet_name" (where "old_outlet_name" will be the old name of your outlet.) when you try to load the view controller from the storyboard. Renaming actions )
Renaming IBActions in code without also changing them in IB gives an error "unrecognized selector sent to instance big_hex_number" when you try to tap the button (or trigger the action for other controls.)
You should open your storyboard in the main editor and open the source in the assistant editor, then control-drag from your button in IB into your source code just below your other outlet at the top of your class.
Your button needs to be an IBOutlet rather than an IBAction. When you ctrl-drag from Interface Builder to your code, make sure you select the 'Outlet' option as shown below:
Then you can change the button title like this:
else {
startButton.setTitle("Button Title", for: .normal)
stopFuncs = true
}
I am able to bind an Observable sequence of data to a table.
Now lets say i have a button on each cell which on click changes the
label of that cell to new value. How to do this ?
I have done so far as follows
I have created an #IBAction for that button in the cell pointing class
then i am doing
label.text = "new text"
but when i scroll down then scroll up, the label show previous value not the new value
previously when i use array and set each value to a cell i used to update that array item and called tableview.reloadData.
how can i do this in RxSwift??
I have done so far
tableview.dataSource = nil (then)
myData.bindTo ... (bind again)
This does not seem to me the right way. so what is the appropriate way to deal with this??
I am able to achive this with RxSwiftCommunity Action
https://github.com/RxSwiftCommunity/Action
ViewController
variable.asObservable().bindTo(mytable.rx.items(cellIdentifier: "cell")) { (row, person, cell) in
if let cellToUse = cell as? TableViewCell {
cellToUse.person = Variable(person)
cellToUse.button1.rx.action = cellToUse.action
}
}.addDisposableTo(disposeBag)
and in cell
class TableViewCell: UITableViewCell {
#IBOutlet weak var label1: UILabel!
#IBOutlet weak var label2: UILabel!
#IBOutlet weak var button1: UIButton!
let disposeBag = DisposeBag()
let action = CocoaAction { input in
return .just(input)
}
var person : Variable<Person>!{
didSet {
self.updateUI()
}
}
private func updateUI(){
person.asObservable()
.subscribe(onNext: {
person in
let name : Observable<String> = Observable.of(person.name)
let age : Observable<String> = Observable.of("\(person.age)")
_ = name.bindTo(self.label1.rx.text)
_ = age.bindTo(self.label2.rx.text)
}).addDisposableTo(disposeBag)
action.elements
.asObservable()
.subscribe(onNext: {
_ in
self.label2.text = "asd"
}).addDisposableTo(disposeBag)
}
}
like before not sure if this is the right way but it worked for me
thanks to (https://rxswift.slack.com/messages/#fpillet) for showing me the way
I have this toolbar in my navigation controller. Now what I am trying to do is when the user selects an item (UIBarButtonItem) in my toolbar, have that item highlighted with a background colour until either the user deselects the item or selects another item. How would I do this?
Here are my selector methods for each item of the toolbar, I connected them via storyboard:
#IBAction func addText(sender: AnyObject) {
annotationSelected = 3
}
#IBAction func drawCircle(sender: AnyObject) {
annotationSelected = 1
}
#IBAction func drawRectangle(sender: AnyObject) {
annotationSelected = 2
}
#IBAction func drawStamp(sender: AnyObject) {
annotationSelected = 4
}
This is all I have done. Here is a screenshot of my toolbar:
Here is what I got:
#IBOutlet var textToolButton: UIBarButtonItem!
#IBOutlet var circleToolButton: UIBarButtonItem!
#IBOutlet var rectangleToolButton: UIBarButtonItem!
#IBOutlet var stampToolButton: UIBarButtonItem!
then
textToolButton.target = self
textToolButton.style = .Done
textToolButton.action = #selector(ViewController.barButtonPressed)
let selectedBackgroundColor = UIImage(color: .redColor())
textToolButton.setBackgroundImage(selectedBackgroundColor, forState: UIControlState.Highlighted, style: .Done, barMetrics: UIBarMetrics.Default)
and then the method
func barButtonPressed(sender: UIBarButtonItem) {
print(sender)
annotationSelected = sender.tag
}
background is still not changing color
I find a same question. May be can help you.
custom-pressed-uibarbuttonitem-backgrounds
I find a easy method to do. You can dray a button to the toolBar,and you will see like this.
And you should change the button's type and Image.
storyboard screenshot
then you should link the button to your viewController.
#IBOutlet weak var textToolButton: UIButton!
and you can do.
let selectedBackgroundColor = UIImage(color: .redColor())
textToolButton.setBackgroundImage(selectedBackgroundColor, forState: .Highlighted)
May be I can help you.
The cleanest way you could do it, is create an overall function where you pass in the button that's been selected. Something like this:
var allButtons = [button1, button2, button3, button4]
func resetTabBar (buttonSelected:UIButton) {
for button in allButtons {
if button == buttonSelected {
button.backgroundColor = "Black"
}
else {
button.backgroundColor = "Blue"
}
}
}
And then in your functions you've created, just pass in the sender like so:
#IBAction func addText(sender: AnyObject) {
resetTabBar(sender)
}
Note: This is assuming you have outlets for all of your buttons. If you don't, add them.