Swift UIButton .setTitle not working - swift

I am programmatically creating a set of buttons on my VC. I am adding a target for the buttons when creating them and in the function that gets called I am changing the background image and trying to remove the title. However, the title is not changing but the background image is changing which doesn't make sense to me.
func createButton(xPos: Int, yPos: Int, width: Int, height: Int, buttonIndex: Int) -> UIButton {
var button = UIButton()
button.frame = CGRect(x: xPos , y: yPos, width: width, height: height)
button.userInteractionEnabled = true
button.layer.masksToBounds = true
var buttonImage = UIImage(named: "Display_Icon")
button.tag = buttonIndex
button.setBackgroundImage(buttonImage, forState: UIControlState.Normal)
button.setTitle("\(buttonIndex)", forState: UIControlState.Normal)
var titleColor = UIColor(red: 0.0, green: 104/255.0, blue: 178/255.0, alpha: 1.0)
button.setTitleColor(titleColor, forState: UIControlState.Normal)
button.addTarget(self, action: "screenSelected:", forControlEvents: UIControlEvents.TouchUpInside)
return button
}
func screenSelected(button: UIButton!) {
if hasError { hasError = false; return }
let screenIndex = button.titleLabel!.text!
if contains(buttonsSelectedArray, screenIndex) {
return
}
buttonsSelectedArray.append(screenIndex)
var buttonImage = UIImage(named: "DisplaySelected_Icon")
button.setBackgroundImage(buttonImage, forState: UIControlState.Normal)
button.setTitle("", forState: UIControlState.Normal)
var titleColor = UIColor.clearColor()
button.setTitleColor(titleColor, forState: UIControlState.Normal)

Try this,
Problem that u add target button in old method(Obj-c)
func createButton(xPos: Int, yPos: Int, width: Int, height: Int, buttonIndex: Int) -> UIButton {
....
....
button.addTarget(self, action: #selector(UIViewController. screenSelected(_:)), for: UIControlEvents.touchUpInside)
return button
}
#IBAction func screenSelected(button: UIButton!) {
if hasError { hasError = false; return }
let screenIndex = button.titleLabel!.text!
if contains(buttonsSelectedArray, screenIndex) {
return
}
buttonsSelectedArray.append(screenIndex)
var buttonImage = UIImage(named: "DisplaySelected_Icon")
button.setBackgroundImage(buttonImage, forState: .normal)
button.setTitle("", forState: .normal)
var titleColor = UIColor.clearColor()
button.setTitleColor(titleColor, forState: .normal)
}

You need to set your button title like this
button.setTitle("Button Title Here", for: UIControlState.normal)
IOS no longer supports using
button.titleLabel?.text= "Button Title"
because you are required to set your title with its UIControlState which is either selected, normal, highlighted or whatever it is.
Please see the documentation from this https://developer.apple.com/reference/uikit/uibutton/1624018-settitle?language=objc

Related

How to create action for UIButton in UIKit

I just created a UIButton and I want to do some action when I click on it i don't know how to do it , here is my way to just create uibutton only !!!:
lazy var test: UIButton = {
let test = UIButton()
test.translatesAutoresizingMaskIntoConstraints = false
test.setTitle("See More Answers", for: .normal)
test.setTitleColor(.systemBlue, for: .normal)
return seeMoreBtn
}()
The modern way is to add the action as a UIAction.
lazy var test: UIButton = {
let test = UIButton()
test.translatesAutoresizingMaskIntoConstraints = false
test.setTitle("See More Answers", for: .normal)
test.setTitleColor(.systemBlue, for: .normal)
let action = UIAction { action in
print("howdy!")
}
test.addAction(action, for: .touchUpInside)
return test
}()
Nicer syntax can be achieved through an extension, as I demonstrate here.
lazy var test: UIButton = {
let test = UIButton()
test.translatesAutoresizingMaskIntoConstraints = false
test.setTitle("See More Answers", for: .normal)
test.setTitleColor(.systemBlue, for: .normal)
test.addTarget(self, action: #selector(self.buttonPressedAction), for: .touchUpInside) // add target
return seeMoreBtn
}()
#objc func buttonPressedAction() {
//This function will get called when u press the button.
//include here what u want to do.
}
#objc func buttonAction() {
print("Button Tapped")
}
test.addTarget(self, action: #selector(buttonAction(_:)), for: .touchUpInside)
I have given the example for create the custom button and the custom label and set constraint in coding. The below code also contains the programmatically button action.
import UIKit
class ViewController: UIViewController {
let button = UIButton(frame: CGRect(x: 100,y: 400,width: 200,height: 60))
var label = UILabel(frame: CGRect(x: 100, y: 200, width: 200, height: 60))
var count : Int = 0
override func viewDidLoad() {
super.viewDidLoad()
button.setTitle("Click Button",for: .normal)
button.backgroundColor = UIColor.blue
button.setTitleColor(.white, for: .normal)
button.addTarget(self,action: #selector(buttonAction),for: .touchUpInside)
label.font = .systemFont(ofSize: 50)
label.backgroundColor = UIColor.gray
label.textAlignment = .center
self.view.addSubview(button)
self.view.addSubview(label)
}
#objc
func buttonAction() {
self.count += 1
self.label.text = "\(count)"
}
}
Output :-
Value of label increases when the button is click.

Implementing the same function for different objects

Newbie coder and learning Swift. I want the function to be applicable for both UIButtons and couldn't figure out how to make it happen for second one.
private lazy var boostButton: UIButton = {
let button = UIButton(type: .custom)
button.frame = CGRect(x: 10, y: 10, width: 80, height: 80)
button.setImage(UIImage(named: "simsek.png"), for: .normal)
button.imageView?.contentMode = .scaleAspectFit
button.contentHorizontalAlignment = .center
button.contentVerticalAlignment = .center
button.layer.cornerRadius = 0.5 * button.bounds.size.width
button.layer.masksToBounds = true
button.addTarget(self, action: #selector(touchDown), for: [.touchDown, .touchDragEnter])
button.addTarget(self, action: #selector(touchUp), for: [.touchUpInside, .touchDragExit, .touchCancel])
return button
}()
private lazy var informationButton: UIButton = {
let button = UIButton(type: .custom)
button.frame = CGRect(x: 120, y: 10, width: 35, height: 35)
button.setImage(UIImage(named: "yenigozlukgri.png"), for: .normal)
button.imageView?.contentMode = .scaleAspectFit
button.contentHorizontalAlignment = .center
button.contentVerticalAlignment = .center
button.layer.cornerRadius = 0.5 * button.bounds.size.width
button.layer.masksToBounds = true
button.addTarget(self, action: #selector(touchDown), for: [.touchDown, .touchDragEnter])
button.addTarget(self, action: #selector(touchUp), for: [.touchUpInside, .touchDragExit, .touchCancel])
return button
}()
These are my buttons. I don't use storyboard but I believe that's not essential for the solution.
#objc func touchDown() {
animator.stopAnimation(true)
boostButton.backgroundColor = .red
//highlightedColor
}
#objc func touchUp() {
animator = UIViewPropertyAnimator(duration: 0.5, curve: .easeOut, animations: {
self.boostButton.backgroundColor = .gray
})
animator.startAnimation()
}
What I want to do is, when one of the buttons are clicked, it should perform the animation. If I add informationButton like the boostButton to my functions, both of them perform the animation even though one button is clicked. It should work for just the clicked one. How can I fix it to be functional for even more buttons ?
Use the parameter
#objc func touchDown(_ sender:UIButton) {
animator.stopAnimation(true)
sender.backgroundColor = .red
//highlightedColor
}
#objc func touchUp(_ sender:UIButton) {
animator = UIViewPropertyAnimator(duration: 0.5, curve: .easeOut, animations: {
sender.backgroundColor = .gray
})
animator.startAnimation()
}

tvOS Button Action

I create a UIButton in tvOS via Swift
let randomBtn = UIButton()
randomBtn.setTitle("Zufällig", forState: .Normal)
let RndNormal = UIImage(named: "RndNormal")
let RndHoover = UIImage(named: "RndHoover")
randomBtn.setImage(RndNormal, forState: .Normal)
randomBtn.setImage(RndHoover, forState: .Focused)
randomBtn.setTitleColor(UIColor.blackColor(), forState: .Normal)
randomBtn.setTitleColor(UIColor.whiteColor(), forState: .Focused)
randomBtn.addTarget(self, action: #selector(ViewController.click(_:)), forControlEvents: UIControlEvents.TouchUpInside)
let screenSize: CGRect = UIScreen.mainScreen().bounds
let screenWidth = screenSize.width
randomBtn.frame = CGRect(x: screenWidth - 150, y: 60 , width: 70 , height: 70)
self.view.addSubview(randomBtn)
But the action never get fired if I press the button, is there anything different in tvOS?
func click(sender: UIButton) {
print("click")
}
In tvOS for Button action UIControlEvents TouchUpInside will not call.
You have to use UIControlEvents PrimaryActionTriggered like below.
randomBtn.addTarget(self, action: #selector(ViewController.click(_:)), forControlEvents: UIControlEvents. PrimaryActionTriggered)
Also Refer this link if you have any confusion
https://forums.developer.apple.com/thread/17925
randomBtn.addTarget(self, action: #selector(ViewController.click(_:)), forControlEvents: UIControlEvents.PrimaryActionTriggered)
Solved it, its just a other UIControlEvents

Not accessing the button title I want even though I use the right tag in swift

I want to create a tic tac toe style board with x's and o's. This first part works and changes the buttons code successfully.
func buttonAction(sender:UIButton!)
{
print("Button \(sender.tag) tapped")
var tag = sender.tag
print(sender.currentTitle!)
if sender.currentTitle! == "" {
sender.titleLabel!.font = UIFont(name: "chalkduster", size: fontSizeTag)
sender.setTitleColor(UIColor.redColor(), forState: .Normal)
sender.setTitle("X", forState: UIControlState.Normal)
} else if sender.currentTitle! == "X" {
sender.titleLabel!.font = UIFont(name: "chalkduster", size: fontSizeTag)
sender.setTitleColor(UIColor.greenColor(), forState: .Normal)
sender.setTitle("O", forState: UIControlState.Normal)
}else if sender.currentTitle! == "O" {
sender.titleLabel!.font = UIFont(name: "chalkduster", size: fontSizeTag)
//sender.setTitleColor(UIColor.greenColor(), forState: .Normal)
sender.setTitle("", forState: UIControlState.Normal)
}
}
This gives me the right button but no access to the title already in it.
#IBAction func deleteAnswers(sender: UIBarButtonItem) {
var totalBoxes = getTotalNumberOfBoxesInGrid()
var tag = Int()
for tag = 1; tag <= totalBoxes; tag++ {
let button = self.view.viewWithTag(tag) as? UIButton
button!.setTitle("", forState: UIControlState.Normal)
}
}
In fact in the second section changing the empty string "" (no title) to a letter, say "P" simply prints a "P" over the existing title. How do I get access the the original title?
I woke with this solution in my head and it works. However it is a solution and not strictly the answer to the question: i.e. how do I get access to a button title set up with send.setTitle. When the "sender" is only used to get a tag# and button titles are set up as I set them up below, delete and other functions needed to access the information work.
func buttonAction(sender:UIButton!)
{
print("Button \(sender.tag) tapped")
var tag = sender.tag
print(sender.currentTitle!)
if var button = self.view.viewWithTag(tag) as? UIButton {
if button.currentTitle! == "" {
button.titleLabel!.font = UIFont(name: "chalkduster", size: fontSizeTag)
button.setTitleColor(UIColor.redColor(), forState: .Normal)
button.setTitle("X", forState: UIControlState.Normal)
myUserValuesDictionary[globalAppD.newPuzzle.name]![tag] = 1
} else if button.currentTitle! == "X" {
button.titleLabel!.font = UIFont(name: "chalkduster", size: fontSizeTag)
button.setTitleColor(UIColor.greenColor(), forState: .Normal)
button.setTitle("O", forState: UIControlState.Normal)
myUserValuesDictionary[globalAppD.newPuzzle.name]![tag] = 2
}else if button.currentTitle! == "O" {
button.titleLabel!.font = UIFont(name: "chalkduster", size: fontSizeTag)
//button.setTitleColor(UIColor.greenColor(), forState: .Normal)
button.setTitle("", forState: UIControlState.Normal)
myUserValuesDictionary[globalAppD.newPuzzle.name]![tag] = 0
}
}
}

How to create a UIButton programmatically

I am trying to build UIViews programmatically. How do I get a UIButton with an action function in Swift?
The following code does not get any action:
let btn: UIButton = UIButton(frame: CGRectMake(100, 400, 100, 50))
btn.backgroundColor = UIColor.greenColor()
btn.setTitle("Click Me", forState: UIControlState.Normal)
btn.addTarget(self, action: "buttonAction:", forControlEvents: UIControlEvents.TouchUpInside)
self.view.addSubview(buttonPuzzle)
The following selector function is:
func buttonAction(sender: UIButton!) {
var btnsendtag: UIButton = sender
}
You're just missing which UIButton this is. To compensate for this, change its tag property.
Here is you answer:
let btn: UIButton = UIButton(frame: CGRectMake(100, 400, 100, 50))
btn.backgroundColor = UIColor.greenColor()
btn.setTitle("Click Me", forState: UIControlState.Normal)
btn.addTarget(self, action: "buttonAction:", forControlEvents: UIControlEvents.TouchUpInside)
btn.tag = 1 // change tag property
self.view.addSubview(btn) // add to view as subview
Swift 3.0
let btn: UIButton = UIButton(frame: CGRect(x: 100, y: 400, width: 100, height: 50))
btn.backgroundColor = UIColor.green
btn.setTitle(title: "Click Me", for: .normal)
btn.addTarget(self, action: #selector(buttonAction), forControlEvents: .touchUpInside)
btn.tag = 1
self.view.addSubview(btn)
Here is an example selector function:
func buttonAction(sender: UIButton!) {
var btnsendtag: UIButton = sender
if btnsendtag.tag == 1 {
//do anything here
}
}
Using a tag is a fragile solution. You have a view and you are creating and adding the button to that view, you just need to keep a reference to it: For example
In your class, keep a reference to the button
var customButton: UIButton!
Create the button and set the reference
let btn = UIButton(frame: CGRect(x: 100, y: 400, width: 100, height: 50))
btn.backgroundColor = .greenColor()
btn.setTitle("Click Me", forState: .Normal)
btn.addTarget(self, action: #selector(MyClass.buttonAction), forControlEvents: .TouchUpInside)
self.view.addSubview(btn)
customButton = btn
Test against this instance in the action function
func buttonAction(sender: UIButton!) {
guard sender == customButton else { return }
// Do anything you actually want to do here
}
You have to addSubview and tag on that btn.