Force Unwrap Optionals from UITextfield - swift

I'm trying to get a value from a UITextfield and it's being returned as optional. I've tried suggested methods of force unwrapping and I'm still receiving Optional("WhateverUserInputHere") instead of 'WhateverUserInputHere'. I've also been looking for a way to make sure the textfield is not empty before retrieving the value, to keep from crashing when force unwrapping. As of now, the value is retrieved after the user hits a button to move to the next screen, and this button is only enabled once the user begins to edit the textfield. If they decide to delete everything within the textfield, however, they can still move forward. Any way to prevent this/make sure button is only enabled once user has finished typing and textfield is not empty?
// Variable used to store value from textfield
var nametemp:String?
var name:String = ""
#IBOutlet weak var NameInput: UITextField!
#IBOutlet weak var NextButton: UIButton!
#IBOutlet weak var TestLabel: UILabel!
// Enables button when textfield has been edited
#IBAction func NameInputEditingDidChange(_ sender: Any) {
NextButton.isEnabled = true
}
// When button is used, value of textfield is retrieved
#IBAction func NextButtonVariableTest(_ sender: Any) {
nametemp = String(describing: NameInput.text)
name = nametemp!
// Label returns optional value
TestLabel.text = "Hello" + name
}
}

Simply use
self.name = NameInput.text!
or
self.name = NameInput.text ?? ""
Once you use String(describing:) the Optional(...) text will be part of your string rather than an optional string and you won't be able to remove it.

Related

if statement executing itself instead of others

I have a code here that, each time I run it, only the if statement which states "All fields are required" works but NOT ONLY when it must be called, it actually runs in place of the others. So whatever I do even when all the fields are complete, I have "All fields are required" as an alert message.
Here is the code, all help is appreciated, thank you in advance.
import UIKit
class RegisterPageViewController: UIViewController {
#IBOutlet weak var userEmailTextField: UITextField!
#IBOutlet weak var userPasswordTextField: UITextField!
#IBOutlet weak var repeatPasswordTextField: 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 registerButtonTapped(_ sender: AnyObject) {
let userEmail = ""
let userPassword = ""
let userRepeatPassword = ""
// Check for empty fields
if (userEmail.isEmpty || userPassword.isEmpty ||
userRepeatPassword.isEmpty)
{
// Display Alert Message
displayMyAlertMessage(userMessage:"All fields are required")
return
}
//Check if passwords match
if (userPassword != userRepeatPassword)
{
// Display an alert message
displayMyAlertMessage(userMessage:"Passwords do not match")
return
}
// Store data
UserDefaults.standard.set(userEmail, forKey:"userEmail")
UserDefaults.standard.set(userEmail, forKey:"userPassword")
UserDefaults.standard.synchronize()
// Display alert message with confirmation
_ = UIAlertController(title:"Alert", message:"Registration is
successfull. Thank you!",
preferredStyle:UIAlertControllerStyle.alert);
_ = UIAlertAction(title:"Ok", style:UIAlertActionStyle.default)
{
action in
self.dismiss(animated: true, completion:nil)
}
}
func displayMyAlertMessage(userMessage:String)
{
let myAlert = UIAlertController(title:"Alert", message: userMessage,
preferredStyle:UIAlertControllerStyle.alert);
let okAction = UIAlertAction(title:"Ok",
style:UIAlertActionStyle.default, handler:nil)
myAlert.addAction(okAction)
self.present(myAlert, animated:true, completion:nil)
}
}
Do you ever assign any values to userEmail, userPassword, userRepeatPassword? You initialize them as empty at the start of the function, and it looks like their values never change.
Instead of declaring them in the function, try using class level variables, and linking them to your textfields in Storyboard.
#IBOutlet weak var userEmail: UITextField!
#IBOutlet weak var userPassword: UITextField!
#IBOutlet weak var userRepeatPassword: UITextField!
#IBAction func registerButtonTapped(_ sender: AnyObject) {
// Check for empty fields
if (self.userEmail.text.isEmpty || self.userPassword.text.isEmpty || self.userRepeatPassword.text.isEmpty) {
// Display Alert Message
displayMyAlertMessage(userMessage:"All fields are required")
return
}
...
}
I suspect that this code is not an accurate representation of your implementation. Would you be able to copy and paste the registerButtonTapped(_:) function unedited?
If it is, I would agree with #unmarshalled: It appears that you have declared each of the variables with an empty string as their value. If the code you have posted is implemented exactly as above, that is the cause of your issue.
based on the code you have posted, I would also recommend the following alterations:
get the email, password & repeatPassword from outside the scope of the function: usually, by just pulling it directly from the UI, most commonly from text fields: i.e. userEmailTextField.text
extracting your user defaults keys, and any other string literals you have, into a constants file is good practice and avoid any unnecessary misspelling related bugs.
you don't need to add a handler to a UIAlertAction if all you want it to do is dismiss the alert. UIAlterController will automatically be dismissed automatically: the handler argument has a default value of nil and can be omitted, simply:
let okayButton = UIAlertAction(title: "Ok", style: .default)
Generally speaking, you don't want to store a reference to a shared instance. However, within small local scopes its a little cleaner to do so:
let userDefaults = UserDefaults.standard
userDefaults.set(userEmail, forKey:"userEmail")
userDefaults.set(userEmail, forKey:"userPassword")
userDefaults.synchronize()
Cheers :)
EDIT:
I would suggest extracting the conditional out to a computed property for readability and check if count == 0 rather than isEmpty. The advantage of this is that you can make the computed property more comprehensive, I.e this will check that the strings are not nil or empty. Usually checking the count is enough, but there’s no harm in covering your bases.
As it stands with the current UIKit implementation, UITextField.text can never be nil. That being said, official documentation does not make that guarantee explicitly, so the best way to handle it is to implement it like an optional, below.
So something like:
fileprivate var registrationFormCompleted: Bool {
guard username = usernameTextfield.text,
password = passwordTextField.text,
repeat = repeatPasswordTextField.text,
else {
return false
}
return username.count > 0 &&
password.count > 0 &&
repeat.count > 0
}
In use it would be:
#IBAction func registerButtonTapped(_ sender: AnyObject) {
// Check for empty fields
if !registrationFormCompleted {
// Display Alert Message
displayMyAlertMessage(userMessage:"All fields are required")
return
}
//....
}

Swift 4 adding a label.text int to a button int [duplicate]

This question already has answers here:
Converting String to Int with Swift
(31 answers)
Closed 5 years ago.
I currently have a label that displays the value of a database read. The database has the value as a string. Through viewWillAppear, the database is read and will display the correct value in the label. I also have a button that when pressed, should add 1 to the current label value. When the label value changes, it will send the current value to the database to store.
I have the label displaying correctly. I was able to add a 1 to the label but it added it onto the end of the number instead of adding the two together (ie. the value was 6, button pressed, value is now 61). The database read/write portion is working correctly. The only thing I cannot seem to understand is how to add the two numbers together. It seems like such a simple process but everything that I have tried does not work. Any help is greatly appreciated!
One example of code that I have used:
class ViewController: UIViewController {
#IBOutlet weak var label: UILabel!
var variable = String([])
#IBAction func addOnePressed(_ sender: UIButton) {
var variable = Int(label.text!)!
let number = 1
if let result = variable += number { self.label.text = result }
The main issue is that the property variable is not equal to the local variable variable
I recommend to declare the property variable as Int, set the label in viewDidLoad and increment the property in addOnePressed
class ViewController: UIViewController {
#IBOutlet weak var label: UILabel!
var variable = 0
override func viewDidLoad() {
super.viewDidLoad()
self.label.text = "\(variable)"
}
#IBAction func addOnePressed(_ sender: UIButton) {
variable += 1
self.label.text = "\(variable)"
}
}
PS: The syntax String([]) is confusing. Actually it's simply an empty string ""

How to safely unwrap textField.text and store it safely in an property?

I have 6 textfields that I want to at the push of a button concatenate into a string (in order) and then take that string and convert it to an Int.
I know how to convert the string into an Int.
What I keep getting stuck at is how do I create a property under the IBOutlets that is optional and then store the optionally unwrapped textfield.text into the property?
What I have tried is
#IBOutlet weak var firstTextField: UITextField!
this is the IBOutlet
var firstTextFieldString: String?
that is the property
then later in a function I say
func functionName(textField: UITextField) {
if textField == firstTextField {
if let text = textField.text {
firstTextFieldString = text
}
}
}
The text property of a UITextField is an optional string (String?) and can be assigned to any other variables that are of the same type. It looks like your outlet and property are correct.
You should be able to assign the text property directly to the firstTextFieldString property.
firstTextFieldString = firstTextField.text
If you want a function to be called when a button is pressed, you can mark the function with #IBAction and hook it up in the storyboard.
#IBAction func functionName(textField: UITextField) {
// your function here
}
If you reference all your text fields as outlets, you should be able to write a function that directly accesses the text property of each field and combine them together. It depends on exactly what you want to when the text fields have no value. If you want to treat them as empty strings, you could unwrap them with a default value before concatenating them all together.
#IBAction func functionName(textField: UITextField) {
let first = firstTextField.text ?? ""
let second = secondTextField.text ?? ""
let third = thirdTextField.text ?? ""
// etc...
let result = first + second + third + ...
// etc...
}

Set maximum characters (to one) in a NSTextfield in Swift

How do i set the maximum amount of characters in multiple NSTextfields (OSX cocoa app, NOT iOS) to one in Swift?
Please explain how to do it, because I'm a complete newbie when it comes to OSX app development and therefore I don't understand short answers like "Use NSFormatter", because I have no idea what it is and how to implement it. Like Examples
There's no built-in way to simply set the maximum, I think because you need to decide what behavior you want. For example, if there's already one character in the field, and the user enters a second character, what should happen? Should the 2nd character be ignored? Replace the first? Beep?
In any case, you can get whatever behavior you want using the NSText Delegate methods. Make your view controller (or whatever object has the logic) a delegate of the text field, and implement the various delegate method(s) to do what you need.
Again, the exact behavior is up to you, but if I were implementing this, I might be inclined to make the text field always use the last character entered (such that, if one character is already present, pressing a second replaces the first). To do that, you'd want to override textDidChange to look at the value of the text field, and modify it if appropriate. Something like:
class ViewController: NSViewController, NSTextFieldDelegate {
#IBOutlet weak var textField: NSTextField!
override func controlTextDidChange(obj: NSNotification) {
if self.textField.stringValue.characters.count > 1 {
self.textField.stringValue = String(self.textField.stringValue.characters.last!)
}
}
}
You don't need to limit the characters a user will enter just only look at the first character entered. In fact, it is probably better since you will always have to handle possible user errors. If you want to you can issue an alert that they entered too many by getting the characters.count. You might want an alert if they don't answer at all. The code below will work as is if you set up a storyboard with 1 NSTextField and one button and connect them. If you have more than one textfield, i.e. like a multiple choice test, just set up all the text fields the same way.
import Cocoa
class ViewController: NSViewController {
#IBOutlet weak var firstLetter: NSTextField!
Add as many text fields as you need:
#IBOutlet weak var secondLetter: NSTextField!
#IBOutlet weak var thirdLetter: NSTextField!
etc.
#IBAction func button(sender: AnyObject) {
var firstEntry = firstLetter!.stringValue
var index1 = firstEntry.startIndex
if firstEntry.characters.count > 1 {
runMyAlert("Bad USER! ONLY ONE Character!")
}
if firstEntry == "" { //left it blank
runMyAlert("You need to enter at least one character!")
exit(0) //or you'll crash on next line
}
var nameLetter1:Character = firstEntry[index1]
print( "First Letter == \(nameLetter1) ")
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override var representedObject: AnyObject? {
didSet {
// Update the view, if already loaded.
}
}
func runMyAlert( alertMessage: String){
var myWindow = NSWindow.self
let alert = NSAlert()
alert.messageText = "ERROR ERROR ERROR"
alert.addButtonWithTitle("OK")
alert.informativeText = alertMessage
alert.runModal()
}
}

Assigning text field value to variable in Swift

I am trying to learn Swift and it is turning out to be more different from other languages than I expected...
I just want to store the value of a user's input as an integer in a variable.
My attempts result in the following error:
"fatal error: unexpectedly found nil while unwrapping an Optional value"
I have tried this multiple ways and can't seem to come up with a solution, I know there must a simple way to do this.
var intNumber: Int = 0
#IBOutlet weak var txt_Number: UITextField!
for view in self.view.subviews as [UIView]{
if let txt = view as? UITextField
{
if let txtData = txt.text where txtData.isEmpty
{
// Error Message
}
else
{
intNumber = Int(txt_Number.text)
}
}
}
I know the above code isn't correct, but I think that's the closest to correct I have come. I seem to be missing something as far as unwrapping goes. I understand the principal of unwrapping, but nothing I have tried will compile, or if it does compile then it fails with the error above when the code is initiated (code is initiated when a button is pressed).
Thank you in advanced for any help!
A couple of thoughts:
Make sure your outlet is hooked up to txt_Number. All of that code checking to make sure it's not nil is not necessary if (a) it's an outlet you hooked up in IB; and (b) you're not doing the above code before the view is completely loaded (i.e. viewDidLoad was called).
If the outlet is not hooked up, you'll see an empty dot on the left margin:
If it is hooked up correctly, you'll see a filled in dot on the left margin:
If everything is hooked up correctly, you can just do:
guard let txtData = txt_Number.text, let value = Int(txtData) else {
// report error and then `return`
return
}
intNumber = value
If you want to get fancy, you might want to ensure the user only enters numeric values by
In viewDidLoad, specify that the keyboard is for decimal numbers only.
txt_Number.keyboardType = .NumberPad
Or you can specify this in IB, too.
Specify a delegate for the text field and only allow them to enter numeric values. (This might seem redundant based upon the prior point, but it's not, because you have to also anticipate them pasting in a string to the text field.)
See https://stackoverflow.com/a/26940387/1271826.
For starters, you don't have to iterate over subviews if you have direct reference txt_Number, but this is not an essence of your question.
if let semantics will let you unwrap any optional inside {} brackets, so the most visible solution here is to:
if let unwrappedString = txt_Number.text {
if let unwrappedIntegerInit = Int(unwrappedString) {
intNumber = unwrappedIntegerInit
}
}
My full example from playgrounds:
var intNumber: Int = 0
var txt_Number: UITextField = UITextField()
txt_Number.text = "12"
if let unwrappedString = txt_Number.text {
if let unwrappedIntegerInit = Int(unwrappedString) {
intNumber = unwrappedIntegerInit
}
}
print(intNumber)
Or you can use guard inside a function:
func parse() {
guard let text = txt_Number.text, let number = Int(text) else { return } // no text
intNumber = number
}
TIP:
You have to unwrap txt_Number.text and Int(text) separately cause Int(text) has to have nonoptional argument.
Did you try with this?
if let txtData = txt.text where !txtData.isEmpty
{
intNumber = Int(txtData)
}
else
{
// Error Message
}
ADD:
Int() function returns an Optional. If you are sure that the value is correct, you can force the unwrapping by using ! at the end of the variable name (when you are using it), otherwise just put the question mark ?
tried below code to assign value of TextField to variable of float type and all bug disappear like magic
#IBOutlet weak var txtamount: UITextField!
#IBOutlet weak var txtrate: UITextField!
#IBOutlet weak var txtyear: UITextField!
#IBOutlet weak var lblresult: UILabel!
#IBAction func btncalculate(_ sender: UIButton)
{
print("button is clicked")
var amount,rate,year,answer : Float
amount = Float(txtamount.text!)!
rate = Float(txtrate.text!)!
year = Float(txtyear.text!)!
answer = (amount * rate * year) / 100.0
}