I am just learning the swift basics and thought it would be a good idea that I try using my skills and a problem appeared. I have tried everything I know can someone help. My image below.
First of all please post text, not images
You have to use the (IBOutlet) instance number rather than the type UIButton and you have to use the proper API
number.setTitle(String(score), for: .normal)
But in an IBAction I'd declare the method with the static sender type (rather than unspecified Any) and use that
#IBAction func touched(_ sender : UIButton) {
score += 1
sender.setTitle(String(score), for: .normal)
}
If you want to change the title of a button, you need to do this:
button_Outlet_Name.setTitle(title: String?, for: UIControlState)
or
button_Outlet_Name.title.text = "New Title"
Remember to do this on your button OUTLET, not on the UIButton class
You cannot change the your button's title that way, what you have done there by writing
UIButton.title = String(score)
This means you are calling a static method of UIButton class and the name of the method is title.
If you want to change the button's tite you can do that the below way:
Step 1: Take a reference of your button by ctrl+drag.
Step 2: Inside your IBAction you need to write:
yourButton.setTitle("\(score)", for: .normal)
Here you are accessing the static method of the UIButton class. If you want to set the title, you need to do so on the instance.
Based on what you have, within the IBAction, you can cast the sender as a UIButton and then set the title. You’d also do that for a specific state since the titles are closely related to the the state for a UIButton.
if let btn = sender as? UIButton {
btn.setTitle(“\(score)”, forState: .normal)
}
You could have also used the IBOutlet reference instead.
number.setTitle(“\(score)”, forState: .normal)
Whenever you use \(variable) within a string, it uses the string value of the variable to be displayed in the string.
I'm not sure what are u trying to do but if you want to change the title of the clicked button u can do like this:
#IBAction func touched(_ sender: Any) {
score += 1
// check if the sender is UIButton
if let button = sender as? UIButton {
//change your button title
button.setTitle("\(scroe)", for: UIControlState.normal)
}
}
Related
I have a button that contains a finger print image like the picture above. that fingerPrint button has a function to segue to viewController2. that fingerPrint button exists on the viewController1.
when the viewController1 is opened for the first time, I will get a data from the server, if I don't have that data, I shouldn't segue to viewController2 .
but sometimes we have an error as the response of my request. if I get the error response, then I want that finger button to be rectangular button that has 'Refresh' as the title and has different function to make request again to the server
how to achieve change the shape of existing UI Button?
class ViewController1 : UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
getDataFromServer()
}
#IBAction func fingerPrintButtonDidPressed(_ sender: Any) {
}
func getDataFromServer() {
// send request to get data from server
}
}
It is usually best to do it either all in code or all in storyboard. To do it in storyboard I suggest one of the following:
Create 2 buttons and in code hide one or another depending on your state
Assign different images and texts for different button states (there is a dropdown in interface builder) and then change the state of a button in runtime
To do it in code overall I suggest simply changing the values.
Assume you have something like this:
enum ViewState {
case idle
case success
case failed
}
var state: ViewState = .idle {
didSet {
refreshButton()
}
}
Now you can set your state when you get a response or on any event needed. All you need to implement is refreshButton.
func refreshButton() {
switch state {
case .idle:
button.setTitle(nil, for: .normal)
button.setImage(fingerprintImage, for: .normal)
button.backgroundColor = .clear
case .success:
button.setTitle(nil, for: .normal)
button.setImage(fingerprintImage, for: .normal)
button.backgroundColor = .clear
case .failed:
button.setTitle("REFRESH", for: .normal)
button.setImage(nil, for: .normal)
button.backgroundColor = .green
}
}
You can then use the same switch inside your button action (on press).
if isError
{
button.type = .system
button.backgroundColor - UIColor.green
button.setTitle("REFRESH" for: .normal)
button.addTarget(--------)
}
else
{
button.type = .custom
button.setImage(UIImage(named: "yourImageName.png") for: .normal)
button.addTarget(--------)
}
Simple Solution is : Use two buttons one for figure Image second for Refresh text. And use button isHidden property vice-versa.
For Auto layout
If you are using Auto layout then use constraint IBOutlet and change it's constant property value. it will change your button height or width.
For Auto resize
if you are using Auto resize than you can change you button frame which you want
I'm trying to create a custom class that creates a button. I'm having trouble adding a target to that button inside it's class. This is my code
class SelectButton{
var button:UIButton = UIButton()
init(button_frame: CGRect, button_title: String, connected: [UIButton]?){
self.button.frame = button_frame
self.button.setTitle(button_title, for: UIControlState.normal)
self.button.addTarget(self, action:#selector(self.buttonPressed), for: .touchUpInside)
}
func construct() -> UIButton {
return self.button
}
#objc func buttonPressed() {
print("Button Clicked")
}
}
The problem is that I can't connect an action on button click. This works if it's used outside my class but not inside.
Usage of the class
let test = SelectButton(button_frame: CGRect(x:50, y:50, width: 250, height:150), button_title: "Test button", connected: nil).construct()
self.view.addSubview(test)
When someone taps the button, usually you want something to happen somewhere else in your app (like in one of your view controllers or in some other UI element). The way the IBAction is set up right now, you have it so that something will trigger or happen within the button itself when someone taps on it. If you want to handle a button tap programmatically instead of ctrl dragging from the button into the view controller, you can do it this way if you prefer. First, add this code into the view controller:
#IBAction func buttonPressed(sender: UIButton) {
}
Then you can either add the selector programmatically by adding this method into your view controller:
myButton.addTarget(self, action:self.buttonPressed(sender), for: .touchUpInside)
Or by going to the connections inspector and dragging from the touch up inside over to the IBAction dot in your view controller code. Also, as someone else pointed out in the comments you should make your button inherit from UIButton by adding this to your class declaration:
class SelectButton: UIButton {
. . .
}
Nothing is holding a strong reference to your SelectButton instance, so as soon as the function that creates test exits, that instance is released.
The button itself is retained because you have added it as a subview. Therefore, it is still visible but there is no longer an object to respond to the action.
You either need to use an instance property rather than a local variable for test, or, preferably have SelectButton inherit directly from UIButton
I'm relatively new to Swift programming and just learned from this article on Stack Overflow that I can't change UIButton text via the 'sender' argument in #IBAction code, but must setup an #IBOutlet from the button and use methods on the outlet variable. How broad of a rule is that? What methods are OK to apply to the 'sender' argument, and which are not?
I don't know what they're referring to in that post you've linked to, as it's not correct. You don't need an #IBOutlet for anything specifically. It doesn't grant any special powers to the button, it's just a handy pointer to the object you can use.
You of course need a pointer to the object if you want to call it's methods, but the sender attribute to an #IBAction is just as good for that IBAction's code.
You do have to make sure the sender is the right type.
For example:
#IBAction func buttonPressed(sender: UIButton) {
sender.setTitle("New Title", forState: .Normal)
}
That will work fine and change the button tapped. Doesn't matter if there's an #IBOutlet pointing to it anywhere. The sender variable is all you need.
In some cases, you'll want to use an AnyObject type for sender, in which case you'll need to check the type first:
#IBAction func buttonPressed(sender: AnyObject) {
if let button = sender as? UIButton {
button.setTitle("New Title", forState: .Normal)
}
}
Now, if you wanted to change a different button's title, then an #IBOutlet can make it easier.
#IBOutlet weak var someOtherButton: UIButton!
#IBAction func buttonPressed(sender: UIButton) {
someOtherButton.setTitle("New Title", forState: .Normal)
}
But again, an #IBOutlet isn't required (it is recommended). To show #IBOutlet doesn't have any special powers, you could set a tag value (e.g. 100) on the button in Interface Builder and use code like this:
#IBAction func buttonPressed(sender: AnyObject) {
if let button = view.viewWithTag(100) as? UIButton {
button.setTitle("New Title", forState: .Normal)
}
}
The 100 number I've used here is arbitrary and could be any number so long as you only use the number for one item in the view.
#IBAction func buttonClicked(sender : AnyObject) {
println("Button was clicked", sender)
}
here sender means your button's reference. you can perform different on button on click by using sender like sender.backgroundColor etc.
Hope this will help :)
The sender argument you mention is part of the Target-Action Mechanism.
The sender parameter usually identifies the control sending the action message (although it can be another object substituted by the actual sender). The idea behind this is similar to a return address on a postcard. The target can query the sender for more information if it needs to. If the actual sending object substitutes another object as sender, you should treat that object in the same way. For example, say you have a text field and when the user enters text, the action method nameEntered: is invoked in the target:
As the sender could be substituded, there is no guarantee that someone could use another sender in the parameter if calling it manually, while if you own a reference to your button in your class, via an IBOutlet, then it could sometimes be wiser to use it for any method you expect to call as you are sure that it refers to the button.
However, if you are sure the method is only linked with the correct sender, you could potentially call any method.
The question would not as much be "what action can I call" but "am I really sure sender really is the relevent button"
I'm in the process of learning Swift and I have a basic question. I don't want to use a Storyboard and I want to create a button with code. At the moment, I code my button this way:
let button1: UIButton = UIButton.buttonWithType(UIButtonType.Custom) as UIButton
button1.setImage(UIImage(named: "myImage.png"), forState: UIControlState.Normal)
button1.addTarget(self, action: "myMethod", forControlEvents: UIControlEvents.TouchUpInside)
button1.frame = CGRectMake(0, 0, 25, 25) // then I add this button to a navigation control
This works, but I'm looking for something slightly different. That is: I want to create a class, I want to pass at least the image name, the method the button must call and the frame. Moreover, I want to instantiate the button in my ViewController whenever I want.
I found many posts here but no post was really useful (some code did not work).
Can you help me?
enum SPBarButtonTypes {
case openDrawer
case loginInfo
}
class SPBarButtonFactory: NSObject {
class func createBarButtonItemOfType (buttonType: SPBarButtonTypes, withTarget buttonTarget: AnyObject, andAction buttonAction: Selector) -> UIBarButtonItem {
var returnButton: UIBarButtonItem = UIBarButtonItem()
returnButton.target = buttonTarget
returnButton.action = buttonAction
switch buttonType {
case .openDrawer:
returnButton.image = UIImage(named: "ic_menu")
case .loginInfo:
returnButton.image = UIImage(named: "ic_info_outline")
default: NSLog("Wrong BarButton type")
}
return returnButton
}
}
ADDED TO IMPROVE COMMENT
It just "seams" like a class nested in another class, but it really is Swifts way to declare a class-method....
This line declares a class named SPBarButtonFactory
class SPBarButtonFactory...
This line declares a class-method of SPBarButtonFactory
class func createBarButtonItemOfType...
Simple question here. I have a UIButton, currencySelector, and I want to programmatically change the text. Here's what I have:
currencySelector.text = "foobar"
Xcode gives me the error "Expected Declaration". What am I doing wrong, and how can I make the button's text change?
In Swift 3, 4, 5:
button.setTitle("Button Title", for: .normal)
Otherwise:
button.setTitle("Button Title", forState: UIControlState.Normal)
Also an #IBOutlet has to declared for the button.
Just a clarification for those new to Swift and iOS programming. Below line of code:
button.setTitle("myTitle", forState: UIControlState.Normal)
only applies to IBOutlets, not IBActions.
So, if your app is using a button as a function to execute some code, say playing music, and you want to change the title from Play to Pause based on a toggle variable, you need to also create an IBOutlet for that button.
If you try to use button.setTitle against an IBAction you will get an error. Its obvious once you know it, but for the noobs (we all were) this is a helpful tip.
Swift 5.0
// Standard State
myButton.setTitle("Title", for: .normal)
Swift 5:
let controlStates: Array<UIControl.State> = [.normal, .highlighted, .disabled, .selected, .focused, .application, .reserved]
for controlState in controlStates {
button.setTitle(NSLocalizedString("Title", comment: ""), for: controlState)
}
Swift 3:
Set button title:
//for normal state:
my_btn.setTitle("Button Title", for: .normal)
// For highlighted state:
my_btn.setTitle("Button Title2", for: .highlighted)
Changing title when attributed is a bit different :
I just ran into a problem : If you have an UIButton with an Attributed Title, you have to use :
my_btn.setAttributedTitle(NSAttributedString(string: my_title), for: my_state)
as, per Apple SetTitle Doc :
If you set both a title and an attributed title for the button, the button prefers the use of the attributed title over this one.
I had an attributed title and I tried to setTitle on it, with no effect...
Swift 3
When you make the #IBAction:
#IBAction func btnAction(_ sender: UIButton) {
sender.setTitle("string goes here", for: .normal)
}
This sets the sender as UIButton (instead of Any) so it targets the btnAction as a UIButton
As of 12/12/2021 - Swift version 5.5.1^ assuming you already have an IBOutlet linked to yourButton in a normal state.
yourButton.setTitle("Title of your button", for: .normal)
swift 4.2 and above
using button's IBOutlet
btnOutlet.setTitle("New Title", for: .normal)
using button's IBAction
#IBAction func btnAction(_ sender: UIButton) {
sender.setTitle("New Title", for: .normal)
}
Swift 3
let button: UIButton = UIButton()
button.frame = CGRect.init(x: view.frame.width/2, y: view.frame.height/2, width: 100, height: 100)
button.setTitle(“Title Button”, for: .normal)
To set a title for a button in Xcode using swift - 04:
first create a method called setTitle with parameter title and UIController state like below ;
func setTitle(_ title : String?, for state : UIControl.State) {
}
and recall this method in your button action method
like ;
yourButtonName.setTitle("String", for: .state)