UIButton press not working with an IF statement - ios

I am currently trying to get an if statement working only when the user presses on the UIButton which will then run the self.eslTopics.isHidden = false in order to show my UIPickerView. What is the correct syntax of writing the if statement? I currently have a button called "showwheel" which is meant to change the pickerview UI from hidden = true to false.
if showWheel{
self.eslTopics.isHidden = false
}
Xcode is trying to throw an error:
Optional type 'UIButton!' cannot be used as a boolean; test for '!= nil' instead, Replace 'showWheel' with '(showWheel != nil)'
which also doesn't make sense or work.

You can create a IBAction method and connect to TouchDown event of a UIButton.
#IBAction func btnShowWheelTapped(_ sender: UIButton) {
self.eslTopics.isHidden = false
}
NOTE: If you implement button's default touchup inside event then it will be called when touched is lifted from button.
For Reference...

You have to associate an IBAction with the button press and add the code in that method.
#IBAction func toggleVisibility(_ sender: UIButton) {
self.eslTopics.isHidden = false
}

if your variable showWheel is an instance variable of type UIButton! (implicitly unwrapped optional UIButton) then your code is not legal.
In C/C++/Objective-C, it's legal to say
if showWheel
And the compiler takes that to mean "if showWheel is true", and true is equivalent to !0 / !nil.
That is not legal in Swift. In Swift, you must explicitly check for nil for optionals, so your code would need to read
if showWheel != nil
Note that you should NOT put your conditional inside parentheses in Swift. Do not use if (showWheel != nil) like you would in C/C++/Objective-C/Java.

As the error mentions:
Optional type 'UIButton!' cannot be used as a boolean; test for '!=
nil' instead, Replace 'showWheel' with '(showWheel != nil)'
showWheel is type of UIButton, means that if you are typing:
if showWheel { }
it means that it is check if showWheel is nil, it is the same as:
if showWheel != nil { }
which seems to be unrelated to what are you asking for, we already assume that showWheel is not nil.
What you should do -in the IBAction of showWheel- is to call self.eslTopics.isHidden = false directly without any if statement.
If you are not familiar with adding an action to a UIButton, you could check:
How do I add a IBAction to a button programmatically in Swift 4? (programmatically).
Mahendra GP's answer (via Storyboard).

Related

How do I use variable declarations within a function outside of the function in Swift?

I am new to programming and could not find out how I might get the variable data back out of the function I created in swift. I tried returning the variable however I get an error in the compiler.
class ViewController: UIViewController {
#IBOutlet var textField: UITextField!
var userName = String()
#IBAction func returnPressed(_ sender: Any) {
userName = textField.text! //user input will = userName
print("return pressed inside textfield")
print("User name set to \(userName)")
self.view.endEditing(true) //hides keyboard
return (userName)
}
The function activates via the return being button pressed. The variable userName will then equal the users input within the text field.
The problem is that outside of this function, I can no longer call on the variable userName and receive the user input value that was stored earlier.
And I cant seem to get the "return" to work like ive been reading.
First of all userName is an internal variable for your class ViewController and can be accessed in every function. You have to access the variable within some function like viewDidLoad, viewWillAppear or any of your custom function within your class.
Make any function and access the variable
func test() {
//access here userName
}
All entities in your code (with a few specific exceptions) have a default access level of internal if you do not specify an explicit access level yourself. As a result, in many cases you do not need to specify an explicit access level in your code.
Read more about Access Controls.
Also you are returning something from an IBAction of the button which don't have any return type. You will get a compiler error there.
Generally return of textfields is handled by UITextFieldDelegate. See here.
The delegate method in Swift 3 is
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
return true
}
The function's return statement isn't doing anything because you are not declaring the function as returning anything.
func returnPressed(_ sender : Any) -> String
That would be a function that returns a String.
In this case, you don't need a return statement because you are not capturing the function's result anywhere by calling the function manually.
If you print the value of userName elsewhere in your code after pressing Return, the variable will have captured that value, please make sure to try before saying you're sure it's not working :)

How to get Integer from button title

I have a Button labeled "3x3" now I want to create an Int variable with the value "3" in button click function.
I have tried
let newBoardSizeString = String.localizedStringWithFormat("\(sender.currentTitle?.characters.first)")
let newBoardSize = Int(newBoardSizeString)
The string i get is like this
"Optional(\"3\")"
and Int I get is
nil
I want only 3
This is an XY problem.
You ask: "How do I convert the first character of my button label to an Int."
The real answer is "Don't do that." It is a very bad idea to make the logic of your code depend on display information.
One simple solution is to use the tag property of your button and set the tag value to 3 in IB when you create the button:
let newBoardSize = sender.tag
Note that you either need to set your IBAction up with the sender as type UIButton (the better solution) or cast sender to the correct class in your IBAction.
Another approach is to set up outlets to your different buttons (e.g. threeButton and fourButton) and then in your IBAction, check which button is the sender and use a switch statement to figure out the appropriate value for each button:
func buttonTapped(sender: UIButton) {
switch sender {
case threeButton:
//Use the value 3
case fourButton
//Use the value 4
}
}
!
let newBoardSizeString = String.localizedStringWithFormat("\(sender.currentTitle?.characters.first!)")
let newBoardSizeString = String.localizedStringWithFormat("\(sender.currentTitle?.characters.first)")
if let unwrapped = Int(newBoardSizeString){
let newBoardSize = unwrapped
}
This works.
let newBoardSize = newBoardSizeString as! Int
Did you try ?
Int(newBoardSizeString)!
and make sure you are handling the nil before unwrapping the value.

Setting UITableView editing in Swift

I'm just trying to perform a very simple system API call, setting a UITableView to editing.
However I have no idea what the compiler is complaining about:
let isEditing = self.tableView?.editing
self.tableView?.setEditing(!isEditing, animated: true)
Error Message:
Optional type '_' cannot be used as a boolean; test for '!= nil' instead
Thankful for any advice!
You can just unwrap optional and use !isEditing!, but I believe this approach will be much safer:
if let isEditing = self.tableView?.editing {
self.tableView?.setEditing(!isEditing, animated: true)
}
The question mark next to tableView means that if the property tableView is nil then tableView?.editing must return nil. This results in an optional Bool for the statement let isEditing = self.tableView?.editing
You can fix this using an exclamation mark instead of a question mark (if you are sure 100% that tableView exists), or more cleaner
if let isEditing = self.tableView?.editing {
//If isEditing exists, than self.tableView exists for sure! If it doesn't
//the only possible reason is that tableView is nil so there is no point
//to try to call setEditing on a nil object. If isEditing is nil, the if
//condition will fail and you will not get in this scope.
self.tableView!.setEditing(!isEditing, animated: true)
}
Your isEditing variable type is Bool optional so apart true and false , it may have nil value as well and thats because of question mark used in self.tableView?.editing. To make it work you will need to force unwrap its value by using ! in either self.tableView!.editing or self.tableView?.setEditing(!isEditing!, animated: true).
Be aware that force unwrapping may be harmful and lead to runtime exceptions, so try avoiding it by using optional unwrapping

Could not find an overload for '=='

I have the following code:
var settingButton:UIButton
settingButton = appDelegate.myFunctionReturningButton()
if (settingButton == nil) {println("WE ARE IN BAD SHAPE!!!!")}
It partly works, but not always. To see what happens in case I do not get what I expect from myFunctionReturningButton(), I added the last line.
But here is the problem and my question:
I get this error message from the Swift compiler:
Could not find an overload for '==' that accepts the supplied arguments
Browsing the net, I kind of understand what that means, but what can I do about it?
How should I write the last line?
For precision:
I have the two following function in AppDelegate.swift and appSettingButton is declared with this line at the top of the AppDelegate class.
var appSettingButton: UIButton = UIButton.alloc()
func registerSettingButton (button:UIButton) {
appSettingButton = button
}
func myFunctionReturningButton() -> UIButton {
return appSettingButton
}
You can't compare a non-optional value to nil because it will never be nil. And you shouldn't use UIButton.alloc() to initialize a button, just use UIButton(). If your logic depends on waiting for this button to be re-defined after initialization of your app delegate subclass, you should make an optional, i.e. UIButton?. Then you can compare it to nil.

Weird error in accessing the text of UIButton in swift

When I write a simple function such as this:
#IBAction func buttonTapped(theButton:UIButton) {
println(theButton.titleLabel.text);
}
It gives me an error: UILabel doesn't have a label called text.
However, when I change it to this:
#IBAction func buttonTapped(theButton:UIButton) {
println(theButton.titleLabel?.text);
}
It works fine, but it prints out something like this:
Optional("1");
What I am doing wrong? I am expecting a value of 1. But it is printing out Optional("1") and secondly, it is working fine when println(theButton.titleLabel?.text);
You can get directly from
let title = theButton.currentTitle!
Optional chaining makes the result optional, so you are printing optional value: https://developer.apple.com/library/ios/documentation/swift/conceptual/Swift_Programming_Language/OptionalChaining.html
With optional binding you can print the value only if it exits.
if let text = theButton.titleLabel?.text {
println(text)
} else {
// text doesn't have value
}
#Kirsteins's answer shows how to obtain the button label text in a safe manner.
Remember that:
UIButton has a titleLabel, which is an optional UILabel.
UILabel has a text property, which is an optional String
so there are 2 optionals in the chain. You can use optional binding as in #Kirsteins's answer, or use forced unwrapping:
let text = theButton.titleLabel!.text!
which however I discourage using, because if any of the 2 is nil you'll have a runtime exception. But for completeness it's worth mentioning.
The buttons titleLabel property returns an optional UILabel, that means it's possible that the button doesn't have a titleLabel.
var titleLabel: UILabel? { get }
If you don't set a title to the button, then the button doesn't have a titleLabel property, the iOS framework adds the titleLabel only if the button has a title, I think this happens to reduce memory.
This is why you have to put the "?" (is called optional chaining you can read about it here http://bit.ly/1vrSOi1) in that line, but this usually get auto completed by Xcode itself.
Kirsteins answers it correctly but misses one small detail
if your object can be nil (optional) you need to check first if it exists to then access its value, like this:
if let text = theButton.titleLabel?.text {
println(text)
}
but you can also ignore the if and just call it like this:
let text : String = theButton.titleLabel?.text
// If theButton.titleLabel don't exists then text will be nil
this happen if the IBOutlet was declared with ? but if you declare with ! that means you know that it could be nil, but you never want it to be nil, for a IBOutlet i prefer this approach since if the IBOutlet is not connected then maybe something is worn with my code.
#IBOutlet var theButton : UIButton!
// and get text value as
theButton.titleLabel!.text
this will ensure theButton.titleLabel could be nil, but in this part of code it is required, hope this helps to understand the difference between optional (?) and optional required (!)

Resources