Why is Optional("Text") - Swift - ios

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!)"

Related

How to prevent iOS app from crashing due to empty textfields?

I need to figure out a solution to prevent the app from crashing when a value is not entered in a textfield. The idea is if the textfield is empty (nil), the value of that textfield will then equal zero. Below I have copied my code:
let taxPercentDou:Double = Double(taxnosign2!)!
Anyone has any suggestions?
You need to stop force unwrapping optionals with the exclamation ! sign:
let b:Double = Double(rent.text!)!// Rent
If rent.text is nil or contains non-numeric text, your app will crash.
You can check for nil and replace it with "0" using the null coalescing operator:
rent.text ?? "0"
You can pass that into the Double initializer like this:
Double(rent.text ?? "0")
However, this will return nil if rent.text contains non-numeric text. You can use the null coalescing operator again to handle this:
let b: Double = Double(rent.text ?? "0") ?? 0.0
You could take this one step farther and write a simple utility method to make it easier to use for all your fields:
func convertToDouble(text: String?) -> Double {
return Double(text ?? "0") ?? 0.0
}
And call it like this:
let b = convertToDouble(rent.text)
Please find the below code. It Might Help you.
static func isNull(aString: AnyObject?) -> Bool
{
//Check for null
if(aString is NSNull){
return true
}
if(aString == nil){
return true
}
let x: AnyObject? = aString
//if string is nsnumber , convert it into string and check
if(aString is NSNumber){
var aString1 : String? = ""
aString1 = String(describing: aString)
return self.isStringEmpty(aString: aString1!)
}
if let aString1 = x as? String
{
return self.isStringEmpty(aString: aString1)
}
else
{
return true
}
}

Elegant way to check if UITextField is empty [duplicate]

This question already has answers here:
How to check if a text field is empty or not in swift
(16 answers)
Checking if textfields are empty Swift
(6 answers)
Closed 4 years ago.
I'm currently working on a project where I use lots of UITextFields. For validation I need to check if the UITextFields are empty. I got a working solution, but it's not that elegant. Maybe someone knows a better way of doing it.
Here is my solution:
// Check if text field is empty
if let text = textField.text, !text.isEmpty {
// Text field is not empty
} else {
// Text field is empty
}
Is there a faster way without unwrapping the text attribute of the text field to find out if it's empty?
Thanks!
How about extending UITextField…
extension UITextField {
var isEmpty: Bool {
if let text = textField.text, !text.isEmpty {
return false
}
return true
}
}
so then…
if myTextField.isEmpty {
}
You can use UIKeyInput property hasText. It works for both UITextField and UITextView:
if textField.hasText {
// Text field is not empty
} else {
// Text field is empty
}
If you would like to check if the text has not only spaces on it:
extension UITextField {
var isEmpty: Bool {
return text?.trimmingCharacters(in: .whitespacesAndNewlines) == ""
}
}
let tf = UITextField()
tf.text = " \n \n "
tf.isEmpty // true
If you have several textfields that you want to check, you could put them all in a guard statement
guard let text1 = textField1.text, let text2 = textField2.text, let text3 = textField3.text, !text1.isEmpty, !text2.isEmpty, !text3.isEmpty else {
//error handling
return
}
//Do stuff
I like to validate each text field depending on the content that should be provided by the user, i.e. emailTextField should contain a valid email address etc. While Ashley Mills answer is convenient, if you regard whitespace " " as text this will return false.
In your case, since you need to validate multiple text fields in the same way, why not extend UITextField as Ashley did with a static class method that can validate each text field passed as an array, in addition to this have other validation methods for each type of text field. Instead of returning a Boolean value I've learned to use guard instead. In this way guard let can be used to check if the validation fails (is nil) and execute the proper code, such as displaying a prompt to the user, or otherwise continue execution.
UITextFieldExtension.swift
import Foundation
import UIKit
extension UITextField {
/// Validates all text field are non-nil and non-empty, Returns true if all fields pass.
/// - Returns: Bool
static func validateAll(textFields:[UITextField]) -> Bool {
// Check each field for nil and not empty.
for field in textFields {
// Remove space and new lines while unwrapping.
guard let fieldText = field.text?.trimmingCharacters(in: .whitespacesAndNewlines) else {
return false
}
// Are there no other charaters?
if (fieldText.isEmpty) {
return false
}
}
// All fields passed.
return true
}
//A function that validates the email address...
func validateEmail(field: UITextField) -> String? {
guard let trimmedText = field.text?.trimmingCharacters(in: .whitespacesAndNewlines) else {
return nil
}
//email addresses are automatically detected as links in i0S...
guard let dataDetector = try? NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue) else {
return nil
}
let range = NSMakeRange(0, NSString(string: trimmedText).length)
let allMatches = dataDetector.matches(in: trimmedText,
options: [],
range: range)
if allMatches.count == 1,
allMatches.first?.url?.absoluteString.contains("mailto:") == true
{
return trimmedText
}
return nil
}
func validateUserName(field: UITextField) -> String? {
guard let text:String = field.text else {
return nil
}
/* 3 to 12 characters, no numbers or special characters */
let RegEx = "^[^\\d!##£$%^&*<>()/\\\\~\\[\\]\\{\\}\\?\\_\\.\\`\\'\\,\\:\\;|\"+=-]+$"
let Test = NSPredicate(format:"SELF MATCHES %#", RegEx)
let isValid = Test.evaluate(with: text)
if (isValid) {
return text
}
return nil
}
/*6 to 16 Characters */
func validatePassword(field: UITextField) -> String?{
guard let text:String = field.text else {
return nil
}
/*6-16 charaters, and at least one number*/
let RegEx = "^(?=.*\\d)(.+){6,16}$"
let Test = NSPredicate(format:"SELF MATCHES%#", RegEx)
let isValid = Test.evaluate(with: text)
if (isValid) {
return text
}
return nil
}
}
Meanwhile, elsewhere...
if (UITextField.validateAll(textFields: [emailTextField, nameTextField])) {
// Do something
}

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!")
}
}
}

How to check nil string in if condition swift

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")
}
}

How to check if a textFieldView is empty or has no spaces?

textField.text.isEmpty
textField.text != ""
These two functions regard spaces as characters. However, I would like my to recognise when the text field has no spaces or is not empty.
Just check if the trimmed string is empty
let isEmpty = str.stringByTrimmingCharactersInSet(.whitespaceAndNewlineCharacterSet()).isEmpty
You can even put it in an String extension:
extension String {
var isReallyEmpty: Bool {
return self.stringByTrimmingCharactersInSet(.whitespaceAndNewlineCharacterSet()).isEmpty
}
}
It even works for a string like var str = " ​ " (that has spaces, tabs and zero-width spaces).
Then simply check textField.text?.isReallyEmpty ?? true.
If you wanna go even further (I wouldn't) add it to an UITextField extension:
extension UITextField {
var isReallyEmpty: Bool {
return text?.stringByTrimmingCharactersInSet(.whitespaceAndNewlineCharacterSet()).isEmpty ?? true
}
}
Your code becomes textField.isReallyEmpty.
In Swift 4,
extension String {
var isReallyEmpty: Bool {
return self.trimmingCharacters(in: .whitespaces).isEmpty
}
}
I used this from #Pieter21 's link.
It works for as many blank spaces a user could enter.
let myString = TextField.text
let trimmedString = myString!.stringByTrimmingCharactersInSet(
NSCharacterSet.whitespaceAndNewlineCharacterSet()
)
if trimmedString != "" {
// Code if not empty
} else {
// Code if empty
}

Resources