When I use titlelabel.text, it can print my results normally, but when I use currenttitle, it returns nil. I checked the document. currenttitle and titlelabel.text are quick access methods, but why do I get different results
#IBAction func numBtnPress(_ sender: UIButton) {
print(sender.titleLabel?.text)
print(sender.currentTitle)
}
The screenshot of the problem is as follows
Thanks everyone, I solved the problem,my button style is pain! When I change it to default it works! The same reason in pain mode,title text position is not working. I changed it to default, now it works!
I'm also building a calculator app and I can confirm changing the button style from Plain to Default solves the problem of sender.currentTitle returning nil.
I'm building a Quizz app and I can confirm changing the button style from Plain to Default solves the problem of sender.currentTitle and sender.titlelabel?.text returning nil/not Working.
After some search i found this.
var res = (sender as AnyObject).currentTitle
Related
I'm following the Apple Pie project from Apple's Develop in Swift Fundamentals book (pp. 333 - 362). There was a weird error where getting a button's title seemed to cause an exception.
"Fatal error: Unexpectedly found nil while unwrapping an Optional value"
#IBAction func letterButtonPressed(_ sender: UIButton) {
sender.isEnabled = false
let letterString = sender.title(for: .normal)! <-- offending code
let letter = Character(letterString.lowercased())
}
I figured out the fix which involved setting the button's Style to default instead of Plain. However, I don't understand why the Plain style would return nil in the first place. Any ideas?
I figured out the fix which involved setting the button's Style to default instead of Plain.
I think this is because when you set the style to "Plain", you are effectively using the UIButton.Configuration API introduced in iOS 15. You are basically doing something like this:
button.configuration = .plain()
And setting the title in the storyboard would set the title of the configuration, rather than calling setTitle(_:for:). You can think of this as:
button.configuration?.title = "..."
This is why you can't get the title using title(for:), but you should be able to get the title you set in the storyboard using button.configuration?.title.
In my swift iOS application, I have a simple UISwitch control. I have connected the value changed outlet to my #IBAction. The code looks like this:
#IBAction func userDidSelectVisibiltySwitch(_ sender: Any) {
if self.visibilitySwitch.isOn {
if badCondition {
self.visibilitySwith.setOn(false, animated: false)
return
}
} else { // Strangely, it executes the else (I think because the compiler is evaluating the isOn condition again when it arrives to the else {}
// work to be done if the user has turned off the switch
}
}
I suspect that in this case, as I am turning the switch off before the else is evaluated, the compiler executes the else {} statement because it evaluates the above isOn expression again. But how is that possible, given that I placed a 'return' instruction ? that is really beyond me. A confirmation of my suspect comes from the fact that if I dispatch_async using GCD the 'self.visibilitySwith.setOn(false, animated: false)' statement, it works properly without executing the else {} statement, because the evaluation of the else takes place before the control is turned off by my statement. My code now looks like this, and it works:
#IBAction func userDidSelectVisibiltySwitch(_ sender: Any) {
if self.visibilitySwitch.isOn {
if badCondition {
DispatchQueue.main.async {
self.visibilitySwith.setOn(false, animated: false)
}
return
}
} else { // In this case it is normal, it does not execute the else {}
// work to be done if the user has turned off the switch
}
}
I think that I am missing something important of swift in this case. Any help is greatly appreciated. I have already provided a solution, but I want to understand the problem. Thanks a lot
Rather than accessing the UISwitch via your sender argument, you go directly to what I assume is the IBOutlet value. Instead of that approach, you can access the sender as outlined below:
#IBAction func userDidSelectVisibiltySwitch(_ sender: UISwitch) {
if sender.isOn && badCondition {
sender.setOn(false, animated: false)
} else { // In this case it is normal, it does not execute the else {}
// work to be done if the user has turned off the switch
}
}
The reason your fix is working is likely because of a slight delay introduced by the dispatch call which allows for the IBOutlet value to update its value.
I have also gone ahead and combined your if statement, as the sample you provide does not require a nested check.
UPDATED BASED ON RMADDY'S COMMENT
This being the solution struck me a bit of code smell, and upon further investigation, I was able to reproduce the scenarios described by OP. This was accomplished by setting the action in Storyboard as seen here:
With that setting, I saw the following:
Original code posted by OP would fail
Adding the DispatchQueue as demonstrated by OP would correct the switch after a brief delay
My posted solution would correctly work
Assuming that this is what the OP has done, then the first correction would be to change the event to Value Changed. Then, as stated by rmaddy in the comment, this would succeed regardless of whether you use the argument or the IBOutlet. Based on the original question, my interpretation was that there was an issue of the outlet value and the switch's state in the interface being out of sync.
enter image description hereI'm a beginner and made a prototype of a calculator app in Xcode. It works great. But to make it more easier to use and add features I thought of adding a Clear Button too. I need help in doing that with my existing code. Please, if possible, give me all steps in detail.
The Code-
The User Interface-
How can I add a All Clear Button to it so the displayed number is 0?
Please try the given below code
#IBAction func ClearButtonAction(sender: AnyObject)
{
your_TextfieldName.text = ""
}
"where Textfield is Outlet Of Your Textfield "
#IBAction func Tap_Save(_ sender: UIButton)
{
TextField.text = " "
}
I am making a customized iOS 8 keyboard. I created a button called Return and I'm stuck because I don't know how to make Return or Enter key work properly. I found many textFielsShouldReturn tutorials but I don't think it belongs to iOS keyboard extensions.
Okay. I got it so easy in short time. This is what i did.
#IBAction func returnPressed(sender: AnyObject) {
var proxy = textDocumentProxy as UITextDocumentProxy
proxy.insertText("\n")
}
I'm new to programming so keep that in mind. I have looked at several other questions on this site, and tried the answers they gave, but those haven't worked for me. The code I am trying to use to change the button to is this:
#IBAction func AnswerButtonA(sender: UIButton)
{
[AnswerButtonA setTitle:#"Hello World" forState:UIControlStateNormal];
}
This is the most common method to do this I have found but it brings up several errors "Expected declaration" "Expected attribute name" "expected ',' separator, and a few others.
Another thing I tried that others suggested is:
#IBAction func AnswerButtonA(sender: UIButton)
{
AnswerButtonA.setTitle("Hello World")
}
This as well as a few other things I've tried all bring up the error "'(UIButton) ->()' does not have a member named 'setTitle'.
I realize this may be a stupid question but I can't figure it out. This is the first app I have tried to develop on my own and I have done fine until this problem. Any help would be appreciated, and if you could go into detail about what I'm doing wrong that would be amazing!
(I only want the button to change when it is pressed, not when the view is loaded.)
In your first question you're trying to use Objective-C code in a Swift file.
In your second example, you're not passing the control state.
In both instances, as Jeremy Pope points out, you're referring to AnswerButtonA as the method, not the button.
You need to create an outlet to your button (or use sender as in Jeremy's answer).
From there, here's what you're looking for:
answerButtonA.setTitle("Hello World", forState: .Normal)
The method signature will pop up as you're typing:
The button being pressed is being sent as an argument called sender. AnswerButtonA is the method which you created. Just a style note, usually the first letter is lowercase for methods. So again, AnswerButtonA is the method that is called when you click the button, sender is the actual button clicked.
IBAction func AnswerButtonA(sender: UIButton)
{
//sender is the button that was pressed
sender.setTitle("HelloWorld", forState: .Normal)
}
You can try this
#IBOutlet answerButtonA : UIButton!
#IBAction func answerButtonAClicked(sender: UIButton)
{
answerButtonA.setTitle("YourTitle", forState: UIControlState.Normal)
}
Also read the swift style guide for learning conventions of variables names and class names. https://github.com/raywenderlich/swift-style-guide
Try this code, this definitely helps you
#IBAction func AnswerButtonA (sender: UIButton!)
{
sender.setTitle("Hello World", forState: UIControlState.Normal)
}
This one works as well
(sender as AnyObject).setTitle("Un-Down", for: .normal)
sender.title = "my text here"
for Xcode 9.3.1