How to check nil string in if condition swift - ios

So when I press the button I check if both the UITextField and the UITextView have some value inside them, but if they are nil then perform this.
So I tried this, but it didn't work:
#IBOutlet weak var defTextView = UITextView
#IBAction func btnTapped(sender: UIButton) {
if let definitionName = defTextView.text {
print(definitionName)
} else {
print("nil")
}
}
Instead of receiving the word "nil" I got empty Strings bring printed

defTextView.text is empty String "" instead of nil.
Try where clause to check if it is empty:
#IBOutlet weak var defTextView = UITextView
#IBAction func btnTapped(sender: UIButton) {
if let definitionName = defTextView.text where !definitionName.isEmpty {
print(definitionName)
} else {
print("nil")
}
}

Your code should work, however, remember that an empty string is not nil. A UITextView's text is unlikely to be nil, so I would use an if statement to check if it is an empty string, as well as than if let unwrapping.
For example, use this instead:
if let defenitionName = defTextView.text where defTextView.text != nil {
print(definitionName)
} else {
print("none") //Not necessarily nil.
}

try following code
if defTextView.text != nil || !(defTextView.text == "") {
print(definitionName)
} else {
print("nil")
}

The question is actually meaningless because the text of a text view is never nil.
According the documentation the property text of UITextView is an implicit unwrapped optional - unlike UILabel whose text can be nil.
So it's guaranteed to be not nil when it's used and you need only to check for an empty string, optional binding or != nil is not needed.
#IBAction func btnTapped(sender: UIButton) {
let definitionName = defTextView.text
if definitionName.isEmpty {
print("definitionName is empty")
} else {
print("definitionName is not empty")
}
}

Related

Cannot invoke initializer for type 'Double' with an argument list of type '(String?)' - Swift Storyboard

Getting this error trying to convert to a double. Any ideas why?
class ViewController : UIViewController {
#IBOutlet var textField : UITextField!
#IBOutlet var answerButton : UIButton!
#IBOutlet var fahrenheitLabel : UILabel!
#IBAction func tempFieldEditingChange(_ textField: UITextField) {
fahrenheitLabel.text = textField.text
}
#IBAction func showAnswer (_ sender : UIButton) {
let temperatures = ["hot","warm","cool","cold"]
let thresholds : [Double] = [80,60,40,0]
let temperature = Double(textField.text) //<-- (ERROR)
for (i,threshold) in thresholds.enumerated() {
if temperature >= threshold {
fahrenheitLabel.text = temperatures[i]
break
}
}
}
}
Trying to take user input of a temperature and spit out a label with hot warm cool or cold. I know theres something I'm missing please help! Thank you.
textField.text is an optional String, so you need to unwrap it before passing the value to a function that doesn’t accept an optional, such as the Double(_ String:) initialiser.
I would use a guard statement to do so. The string may not be able to be parsed as a Double, so that initialiser also returns an optional, which needs to be unwrapped.
#IBAction func showAnswer (_ sender : UIButton) {
guard let text = textField.text else {
return
}
let temperatures = ["hot","warm","cool","cold"]
let thresholds : [Double] = [80,60,40,0]
if let temperature = Double(text) {
for (i,threshold) in thresholds.enumerated() {
if temperature >= threshold {
fahrenheitLabel.text = temperatures[i]
break
}
}
}
}
}
The UITextField.text property returns an optional String? type. The Double's initializer requires a regular String.
To use the text property, you must first "unwrap" it, i.e. transform it from an optional value into a non-optional. There are several ways to do it:
Forced unwrapping
If you are certain, that the text property is not nil, you may forcibly unwrap it. Be mindful though, as when you try to forcibly unwrap a nil value, your app will crash.
if textField.text != nil {
let temperature = Double(textField.text!)
}
In this case, the text property should never be nil. However, if there were some code changing the property inside the if statement and before the line where the property is forcibly unwrapped, the forced uwrapping might crash.
Optional binding (the preferred way)
This method lets you unwrap the property safely by binding its value to another constant/variable, and once the value is bound, it can be freely used without the possibility of it becoming nil.
if let temperatureValue = textField.text {
let temperature = Double(temperatureValue)
}
The unwrapped temperatureValue constant will remain available and non-optional throughout the whole if-let scope, meaning that up to the closing brace of the if-let statement you can use it freely and will be gone outside the statement's braces. If the textField.text is nil, the inside of the statement's braces will never be executed.
Instead of if-let, you might use the guard-let statement:
guard let temperatureValue = textField.text else {
return
}
let temperature = Double(temperatureValue)
Notice however that any guard statement requires the function to return if the statement fails, but the unwrapped value can be accessed normally in the rest of the function, not only in a closing braces of a statement, like with if-let.
Last thing: the Double's initializer that takes a String also returns an optional value - so in order to use it (e.g. compare to other Double values), you must unwrap it as well:
if let temperature = Double(temperatureValue) {
// compare "temperature" to other Double values
}
This should work with if let way
let atextField = UITextField(frame: .zero)
atextField.text = "55.9"
if let d = Double(atextField.text!) {
print(d)
} else {
print("no")
}
You need to unwrap .text. Here is how I would do it:
class ViewController : UIViewController {
#IBOutlet var textField : UITextField!
#IBOutlet var answerButton : UIButton!
#IBOutlet var fahrenheitLabel : UILabel!
#IBAction func tempFieldEditingChange(_ textField: UITextField) {
fahrenheitLabel.text = textField.text
}
#IBAction func showAnswer (_ sender : UIButton) {
guard let text = textField else {
fatalError("Handle case when textField.text is nil") // TODO
}
guard let temperature = Double(textField) {
fatalError("Handle case when textField.text is nonnil but not a double") // TODO
}
switch temperature {
case ..<40: textField.text = "cold"
case 40..<60: textField.text = "cool"
case 60..<80: textField.text = "warm"
case 80...: textField.text = "hot"
default: fatalError("Non-exhaustive temperature ranges!")
}
}
}

Why is Optional("Text") - Swift

I just started with Swift. So I created a simple application with a label, button and a text field. When you click the button, the app has to change the label with the text of the text field.
class ViewController: UIViewController {
#IBOutlet weak var textLabel: UILabel!
#IBOutlet weak var textField: UITextField!
#IBAction func updateButton(sender: UIButton) {
textLabel.text = "Hi \(textField.text) "
}
The result is
Hi Optional("TextOfTextField")
Okay. So it's a very simple question.
I hope someone can help me.
The text of your textField is an optional value because a text field can sometimes be empty. So, use an if let to unwrap the variable and make sure it's not nil — otherwise your program could crash:
if let text: String = textField.text {
textLabel.text = text
}
So the problem here is that the textField's text is an optional, that you have to unwrap for using it.
Just add an ! to textField.text like this:
textLabel.text = "Hi \(textField.text!)"
Your output will now be Hi TextOfTextField
You have a few safer options to unwrap your optionals:
nil coalescing operator: ??
This will use either textField.text, or, if that's nil, use the other value provided, "?" in this case
textLabel.text = "Hi \(textField.text ?? "?")"
if let statement:
Note that this will only update your text field's text, if it's not nil. You could provide an else statement to deal with that.
if let text = textField.text {
textField.text = "Hi \(text)"
}
guard let statement:
This works similarly like the if let statement, except that your function will end after the statement.
guard let text = textField.text else { return }
textField.text = "Hi \(text)"
Hope this helps :)
One more way can be to use Guard to check if it is not nil.
guard let nameText = textField.text else {
print("break if nil")
return
}
textLabel.text = "Hi \(nameText!)"
Using guard makes sure your app fails early if the condition fails.
In my case for Swift 4.x, I unwrapped by using below command for option Int? values or Optional list cont:
\(topics?.count ?? 0 )
Using (if let) or (guard let) you can unwrap the value
if let text = textField.text {
textField.text = "Hi \(text)"
}
guard let text = textField.text else { return }
textField.text = "Hi \(text)"
I solved this problem with this for Swift 3;
self.label.text = "\(transaction.amount!)"

Getting a nil/optional error while trying to append an element at a dictionary's key

I am getting the following error:
fatal error: unexpectedly found nil while unwrapping an Optional value.
I think the problem mainly lies in my textField. So I tried unwrapping it by using if let as follows:
if let text = textField.text {
addressDict[rowTapped]! += [text]
}
However, I still got the same error. So I tried the following:
let text: String = textField.text!
addressDict[rowTapped]! += [text]
But this didn't work either; that is, I got the same error.
So, I tried printing textField.text onto the console and it never was nil. The rest of my code is as follows:
import UIKit
var addressDict = Dictionary<Int, Array<String>>()
class MapViewController: UIViewController {
var rowTapped = 0
#IBOutlet weak var textField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func button(sender: AnyObject) {
print(rowTapped)
print(textField.text!)
print(addressDict)
addressDict[rowTapped]! += [textField.text!] //getting the same error
}
Anybody know how to solve this problem?
Here you are using
addressDict[rowTapped]! += [textField.text!]
means
addressDict[rowTapped]! = addressDict[rowTapped]! + [textField.text!]
Initially there is no value in the dictionary for "rowTapped" key (Means array is nil) to append textField.text. That's why the fatal error is happening. So initialize that array and try appending.
You have to first check whether addressDict[rowTapped] is nil.
if let rowInfo = addressDict[rowTapped] {
rowInfo.append(textField.text!)
} else {
// Create an entry for the row.
addressDict[rowTapped] = [textField.text]
}
Using #Dev and and #NRitH answers, I came up with a solution that seems to work. The thing is, I never use rowInfo. It just acts like a checker to see if it is a nil. And the reason why I don't use it is because when I do rowInfo += [textField.text!], the textField.text doesn't go into this dictionary, that is, it doesn't get appended. But if I do:
#IBAction func button(sender: AnyObject) {
if let rowInfo = addressDict[rowTapped] {
addressDict[rowTapped]! += [textField.text!]
} else {
addressDict[rowTapped] = [textField.text!]
}
}
It gets appended and works. However, I'm not sure why rowInfo += [textField.text!] doesn't work.
Edit: You can also write the following so that you don't have the awkward rowInfo there:
#IBAction func button(sender: AnyObject) {
if addressDict[rowTapped] != nil {
addressDict[rowTapped]! += [textField.text!]
} else {
addressDict[rowTapped] = [textField.text!]
}
print(addressDict)
}

NSUserDefaults Loosing Value in Swift

Update: I've tried changing setValue to setObject, and the same error occurred.Upon further investigation with breakpoints and the LLDB, they are nil before the controller is even presented. I'm not saving them right.
I'm trying to simply save a couple of strings of text, and display them on another view using Swift. I'm not sure why I'm having such a hard time. Here is how I'm trying to accomplish this:
VC1
#IBAction func registerTapped(sender : AnyObject)
// Save the login information
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setValue(username.text, forKey: "username")
defaults.setValue(password.text, forKey: "password")
if firstName.text.isEmpty == false {
defaults.setValue(firstName.text, forKey: "firstname")
}
if lastName.text.isEmpty == false {
defaults.setValue(lastName.text, forKey: "lastname")
}
let profileView = ProfileViewController()
self.presentViewController(profileView, animated: true, completion: nil)
}
}
Cool. That looks like the correct way to save strings in UITextFields based upon my research. So, I open up VC2 and try to load the saved text into the new UITextField's, like so:
override func viewDidLoad() {
super.viewDidLoad()
let defaults = NSUserDefaults.standardUserDefaults()
username.text = defaults.stringForKey("username")
password.text = defaults.stringForKey("password")
if let first = defaults.stringForKey("firstname")
{
firstName.text = first
}
if let last = defaults.stringForKey("lastname") {
lastName.text = last
}
}
I get the crash fatal error: unexpectedly found nil while unwrapping an Optional value. I've been digging through tutorials for hours and can't for the life of me figure out what I am doing wrong.
Is it because it an an optional? This is my LLDB output:
Your issue has nothing to do NSUserDefaults, whats nil are your labels username, password, etc. in your second controller.
You should add a segue to your button (the one with registerTapped) to show the second controller and remove the last two lines in registerTapped.
Break your code into steps and debug each one. Your code would crash if your outlet is nil or if the key/value pair doesn't exist. Check that both username and password (The text fields) are not nil, as well as that the defaults results aren't nil:
var text: String?
text = defaults.stringForKey("username")
if let text = text
{
if let username = username
{
username.text = text
}
else
{
println("username field is nil!")
}
}
else
{
println("defaults stringForKey("username") = nil!")
}
text = defaults.stringForKey("password")
if let text = text
{
if let password = password
{
password.text = text
}
else
{
println("password field is nil!")
}
}
else
{
println("defaults stringForKey("password") = nil!")
}

I unwrapped the optional value but still getting this unexpectedly found nil while unwrapping an Optional value

I am new to IOS development and couldn't figure out how to resolve this error. Could any one help me out. Following is my code and the error point on the part of the code where I am using NSNumberFormatter(). waiting for your reply
class ViewController: UIViewController {
#IBOutlet weak var display: UILabel!
var usertyping
= false
#IBAction func appendDigit(sender: UIButton) {
let digit = sender.currentTitle!
if usertyping
{
display.text = display.text! + digit
}
else
{
display.text = digit
usertyping = true
}
}
#IBAction func operate(sender: UIButton) {
let operation = sender.currentTitle!
if usertyping{
enter()
}
switch operation {
case "×":
if operandstack.count >= 2
{
displayValue = operandstack.removeLast() * operandstack.removeLast()
enter()
}
default: break
}
}
var operandstack = Array<Double>()
#IBAction func enter() {
usertyping = false
operandstack.append(displayValue)
println("operandstack=\(operandstack)")
}
var displayValue: Double
{
get{
return NSNumberFormatter().numberFromString(display.text!)!.doubleValue
}
set{
display.text="(\newValue)"
usertyping=false
}
}
}
My guess is that it is failing over because display.text is nil or some invalid value.
Unwrapping an optional doesn't stop it being nil. It says that you realise that it could be nil, but you know that it isn't. If you are wrong and it is nil, it will fail.
Normally, unwrapping optionals for things like you are loading an image from a file. The file could be missing, but you know it isn't in your program, so you can assume the result can never be nil.
In your case, I assume display.text can be nil and you have to explicitly handle it or use optional chaining (the ?).
I see 2 dangerous "!" in this line
return NSNumberFormatter().numberFromString(display.text!)!.doubleValue
One on them could be the cause of your fatal error.
display.text! are you sure text is not nil?
numberFromString returns an optional, are you sure the input you are passing is something the method can transform into a NSNumber?
Hope this helps.
It is because numberFromString returns nil if there is no valid number found.
An NSNumber object created by parsing string using the receiver’s
format. Returns nil if there are no numbers in the passed string.
Reference numberFromString:
If your display.text doesn't have any valid number that statement will crash.
You can fix that by:
var displayValue: Double
{
get
{
var returnVal = NSNumber(int: 0)
if let dVal = NSNumberFormatter().numberFromString(display.text!)
{
returnVal = dVal
}
return returnVal.doubleValue
}
set
{
display.text = "(\newValue)"
usertyping = false
}
}

Resources