I am trying to create a required field in Swift 2. Everytime I run this code I receive no errors, but I never receive an error message with the text field is empty. The segue is always performed. Any idea what I am doing wrong?
Thanks!
#IBOutlet weak var userName: UITextField!
#IBAction func userConfermation(sender: AnyObject) {
if userName.text!.isEmpty {
let alertController = UIAlertController(title: "Error",
message: "Incorrect Password", preferredStyle:UIAlertControllerStyle.Alert)
alertController.addAction(UIAlertAction(title: "Dismiss",
style: UIAlertActionStyle.Default,handler: nil))
self.presentViewController(alertController, animated: true, completion: nil)
} else {
performSegueWithIdentifier("final", sender: self)
}
return
}
Hi you can check the empty string by checking userName.text character count or userName.text == "" whenever is got empty it will give you error and segue will not perfrom
In Swift 2 you can use a guard statement and where !text.isEmpty to check if the text field has text in it or not.
guard let text = textfield.text where !text.isEmpty else {
// do something if it's empty
return
}
print(text) // do something if it's not empty
A good way to do that would be, To create an extension of String and check for isEmpty after trimming whitespace characters :
extension String {
var isBlank: Bool {
return trimmingCharacters(in: .whitespaces).isEmpty
}
}
After that you can check a string like this:
if userName.text!.isBlank {
//do stuff
}
Related
I am working on a checklist app. If the user wants to add a new point on his checklist, he can push the "Add" button and an alert will appear with a UITextField to put his new task in.
alert.addAction(UIAlertAction(title: "Add", style: .default, handler: { (action) in
let textf = alert.textFields![0] as UITextField
if(textf.text != "")
{
checklist.append(textf.text!.capitalized)
}
self.myTableView.reloadData()
}))
self.present(alert, animated: true, completion: nil)
}
Doing it like this will capitalize the words after hitting "Add". But I want that only the first word to be capitalized. Also, I want it to be on the keyboard when it appears so that the first word is capitalized right away. How can I do that?
let alert = UIAlertController(title: "Add new task", message: nil, preferredStyle: .alert)
alert.addTextField { (alertInputTextField) in
}
Use the autocapitalizationType property of the textfield and set it to sentences when you add it...
alert.addTextField { textField in
textField.text = "Some default text"
textField.autocapitalizationType = .sentences
}
Always refer to the documentation, it explains this quite well.
If you need to do this to a String directly just uppercase the first letter of the String.
You can use any of the below function:-
public mutating func capitalizeFirst() {
guard self.count > 0 else { return }
self.replaceSubrange(startIndex...startIndex, with: String(self[startIndex]).capitalized)
}
or
public func capitalizedFirst() -> String {
guard self.count > 0 else { return self }
var result = self
result.replaceSubrange(startIndex...startIndex, with: String(self[startIndex]).capitalized)
return result
}
I am trying to do validation on the entry in a text field in textFieldShouldEndEditing, I check to see if the value is non numeric or out of bounds, then call a function that displays an alert. After the alert is displayed, I set the value to a default and then call other functions to perform calculations.
Regardless of what action I choose to dismiss the alert, editing of the text field is triggered. This is what I want for the first option ("Try Again"), but for the option "Set to Default" I just want to alert to go away and not begin editing of the text field, as the default value was already assigned. I do not understand how alerts interact with first responder status or why the text field is given first responder status again. Relevant code:
func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
var InvalidFlagText: String = ""
let WindIntBool = isStringAnInt(string: textField.text!)
if WindIntBool { //if entered wt is numeric, check to see if out of bounds of data loaded in table
if WindInt < LowestWind || WindInt > HighestWind { //value is out of bounds of data, set to default
txtWind.text = "0"
// display alert
InvalidFlagText = "OutofBounds"
DisplayAlert(InvalidFlag: InvalidFlagText)
}
} else { // if not numeric, set to default value
txtWind.text = "0"
// display alert
InvalidFlagText = "Nonnumeric"
DisplayAlert(InvalidFlag: InvalidFlagText)
}
CalculateResults()
return true
}
func DisplayAlert (InvalidFlag: String) {
var messageText: String = ""
if InvalidFlag == "Nonnumeric" {
messageText = "Please enter a numeric value."
} else if InvalidFlag == "OutofBounds" {
messageText = "Entered value is outside of the valid numeric range. Please enter a valid numeric value"
}
let alert = UIAlertController(title: "That is an invalid entry.", message: "\(messageText)", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Try Again", style: .cancel, handler: nil))
alert.addAction(UIAlertAction(title: "Set to Default", style: .default, handler: { action in
}))
self.present(alert, animated: true)
}
try resign all responders on your alert
alert.addAction(UIAlertAction(title: "Set to Default", style: .default, handler: { action in
//// set your text value before ////
self.view.endEditing(true)
}))
Right or better way:
func DisplayAlert (InvalidFlag: String) {
self.view.endEditing(true)
var messageText: String = ""
if InvalidFlag == "Nonnumeric" {
messageText = "Please enter a numeric value."
} else if InvalidFlag == "OutofBounds" {
messageText = "Entered value is outside of the valid numeric range. Please enter a valid numeric value"
}
let alert = UIAlertController(title: "That is an invalid entry.", message: "\(messageText)", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Try Again", style: .cancel, handler: { action in
self.txtWind.becomeFirstResponder()
}))
alert.addAction(UIAlertAction(title: "Set to Default", style: .default, handler: { action in
/// set default value ////
}))
self.present(alert, animated: true)
}
Not sure what CalculateResults() method does and I assumed the isStringAnInt method as well. Below is the code for the functionality you are expecting.
import UIKit
let kDEFAULT_WIND = "0"
class ViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var txtWind: UITextField!
let HighestWind = 200
let LowestWind = 100
var WindInt = -1
override func viewDidLoad() {
super.viewDidLoad()
txtWind.delegate = self
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
self.view.endEditing(true)
return true
}
func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
if textField.text == kDEFAULT_WIND{
return true
}
var InvalidFlagText: String = ""
let WindIntBool = isStringAnInt(s: textField.text!)
if WindIntBool { //if entered wt is numeric, check to see if out of bounds of data loaded in table
if WindInt < LowestWind || WindInt > HighestWind { //value is out of bounds of data, set to default
InvalidFlagText = "OutofBounds"
DisplayAlert(InvalidFlag: InvalidFlagText)
}
} else { // if not numeric, set to default value
InvalidFlagText = "Nonnumeric"
DisplayAlert(InvalidFlag: InvalidFlagText)
}
// CalculateResults()
return true
}
func isStringAnInt(s : String) -> Bool{
if let val = Int(s){
WindInt = val
return true
}
return false
}
func DisplayAlert (InvalidFlag: String) {
var messageText: String = ""
if InvalidFlag == "Nonnumeric" {
messageText = "Please enter a numeric value."
} else if InvalidFlag == "OutofBounds" {
messageText = "Entered value is outside of the valid numeric range. Please enter a valid numeric value"
}
let alert = UIAlertController(title: "That is an invalid entry.", message: "\(messageText)", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Try Again", style: .cancel, handler: { action in
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now(), execute: {
self.txtWind.text = kDEFAULT_WIND
self.txtWind.becomeFirstResponder()
})
}))
alert.addAction(UIAlertAction(title: "Set to Default", style: .default, handler: { action in
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now(), execute: {
self.txtWind.text = kDEFAULT_WIND
self.txtWind.resignFirstResponder()
})
}))
self.present(alert, animated: true)
}
}
I am trying to validate my credentials(username and password). For some reason the code never enters into the first if loop even when I leave the username and password field empty and click on the Login button.
Attaching the code and a screenshot as well.
Can someone help me fix this.?
import UIKit
class FirstViewController: UIViewController {
#IBOutlet weak var NameField: UITextField!
#IBOutlet weak var PasswordField: UITextField!
#IBAction func textFieldDoneEditing(sender: UITextField){
sender.resignFirstResponder()
}
override func viewDidLoad() {
super.viewDidLoad()
// let stringkey = NSUserDefaults.standardUserDefaults()
// NameField.text = stringkey.stringForKey("savedusername")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func LogIn(sender: AnyObject) {
//let myText = NameField.text;
//NSUserDefaults.standardUserDefaults().setObject(myText, forKey: "savedusername")
//NSUserDefaults.standardUserDefaults().synchronize()
if(NameField == "" || PasswordField == "")
{
let alert = UIAlertController(title: nil , message: "Invalid Credentials!", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "OK", style: .Cancel, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}
if(NameField != "" && PasswordField != ""){
let alert = UIAlertController(title: nil , message: "Login Successfull", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "OK", style: .Cancel, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}
}
}
You're comparing the UITextField to "" rather than its text property.
Try NameField.text etc instead.
In swift below code through we can check textfield empty or not.
if textfield.text?.characters.count == 0 {
print("Empty")
}else {
print("Not Empty")
}
You have tried to compare UITextfield with NSString So your Code will never execute according to Your condition.
Try Using Below code
#IBAction func LogIn(sender: AnyObject) {
if(NameField.text == "" || PasswordField.text == "")
{
//Please Enter valid credential...
}
if(NameField.text != "" && PasswordField.text != ""){
//Login successfully...
}
}
First of all please do not mark duplicate on this question Ive done my research on this topic, and not only have the most recent answers been from over a year ago, but they have also been in C#. Mine also differs from those because I am trying to present my UIView from what I assume to be a child of a child view. But I'm not 100% sure about this. So, here is what my code dump looks like after the suggestions.
import UIKit
import Firebase
class LoginViewController: UIViewController, UITextFieldDelegate{
#IBOutlet weak var usernameTxt: UITextField!
#IBOutlet weak var emailTxt: UITextField!
#IBOutlet weak var passwordTxt: UITextField!
#IBOutlet weak var confirmPassTxt: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func nextScreen(sender: UIButton) {
if(emailTxt.text == "" || passwordTxt.text == "" || confirmPassTxt.text == "" || usernameTxt.text == ""){
let alertController = UIAlertController(title: "Wait!", message: "You didn't fill out the required fields, please do so and try again. ", preferredStyle: .Alert)
let defaultAction = UIKit.UIAlertAction(title: "OK", style: .Default, handler: nil)
alertController.addAction(defaultAction)
self.presentViewController(alertController, animated: true, completion: nil)
}else{
if(validateEmail(emailTxt.text!)){
emailCheck(emailTxt.text!){isValid in if isValid{self.secondRound({ (goodMail, goodPassL, goodPassTxt, nameGood) in
if (goodMail && goodPassL && goodPassTxt && !nameGood){
print("good")
}else{
self.showAlert("Else", description: "Got it?") }
})}else{let alertController=UIAlertController(title: "Whoops!", message: "That email address has already been taken, please try another one", preferredStyle: .Alert)
let defaultAction = UIKit.UIAlertAction(title: "OK", style: .Default, handler: nil)
alertController.addAction(defaultAction)
alertController.parentViewController
self.presentViewController(alertController, animated: true, completion: nil)
}}
}else{
let alertController = UIAlertController(title: "Whoops!", message: "That doesnt appear to be a valid email address, please check your information and try again!", preferredStyle: .Alert)
let defaultAction = UIKit.UIAlertAction(title: "OK", style: .Default, handler: nil)
alertController.addAction(defaultAction)
alertController.parentViewController
presentViewController(alertController, animated: true, completion: nil)
}
}
}
func showAlert(title: String, description: String){
let alertController: UIAlertController = UIAlertController(title: title, message: description, preferredStyle: .Alert)
let defaultAction = UIKit.UIAlertAction(title: "OK", style: .Default, handler: nil)
alertController.addAction(defaultAction)
UIApplication.sharedApplication().keyWindow?.rootViewController?.presentViewController(alertController, animated: true, completion: nil)
self.presentViewController(alertController, animated: true, completion: nil)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let DestinationVC : Login2VC = segue.destinationViewController as! Login2VC
DestinationVC.prepareEmail = emailTxt.text!
DestinationVC.preparePass = passwordTxt.text!
}
func validateEmail(canidate: String) -> Bool {
let emailRegex = "[A-Z0-9a-z._%+-]+#[A-Za-z0-9.-]+\\.[A-Za-z]{2,6}"
return NSPredicate(format: "SELF MATCHES %#", emailRegex).evaluateWithObject(canidate)
}
func nameFilter(input : String)-> Bool{
var profanity : Bool = true
let dataRef = FIRDatabase.database().reference()
dataRef.child("Profanity").observeSingleEventOfType(.Value) { (snap: FIRDataSnapshot) in
if(snap.exists()){
if(snap.value! as! NSArray).containsObject(input){
print("our ears!")
profanity = true
}else{
profanity = false
}
}
}
return profanity
}
func emailCheck(input: String, callback: (isValid: Bool) -> Void) {
FIRAuth.auth()?.signInWithEmail(input, password: " ") { (user, error) in
var canRegister = false
if error != nil {
if (error?.code == 17009) {
canRegister = false
} else if(error?.code == 17011) {
//email doesn't exist
canRegister = true
}
}
callback(isValid: canRegister)
}
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
func secondRound(callback:(goodMail:Bool, goodPassL:Bool, goodPassTxt:Bool, nameGood:Bool)->Void){
let availableEmail : Bool = true
var passwordMatch : Bool = false
var passwordLength : Bool = false
var profanity : Bool = false
if(passwordTxt.text!==confirmPassTxt.text!){passwordMatch=true}else{passwordMatch=false}
if(passwordTxt.text!.characters.count>=6&&confirmPassTxt.text!.characters.count>=6){passwordLength=true}else{passwordLength=false}
if(nameFilter(usernameTxt.text!)){profanity=true}else{profanity=false}
callback(goodMail: availableEmail, goodPassL: passwordLength, goodPassTxt: passwordMatch, nameGood: profanity)
}
}
Essentially, what I am trying to do is:
Check to see if the inputted text is formatted as an email correctly
Check to see if the name is available
Check if the username contains profanity (pulled as a json from firebase)
Check to see if the passwords match
Check too see if the passwords are at least 6 characters in length
Each false result would have its own UIAlertView that results from it, but whenever I try to add these views they do not show up, and the app returns with this error.
Note, the false event does intact appear in the first condition only. Other than that, nothing happens.
This is the error I have been getting, and while it seems pretty straight forward I cannot figure out hoe to fix it, nor find any recent information online on how to accomplish this task.
> Warning: Attempt to present <UIAlertController: 0x7fb513fb8bc0> on
> <myApp.LoginViewController: 0x7fb513c6e0a0> whose view is not in the
> window hierarchy!
The logical answer to this would be:
Hey, why don't you just add the window to the hierarchy and be done?
Well, to that question I have a question, if the window is not apart of the hierarchy, then why is the view itself even displaying. Furthermore, why would the first set of UIAlerts be displaying, but as soon as I get into a nested if they cease? Any ideas on how to fix this terrible error?
Thanks all
I have some issue with my first code in Swift, when I'm running it, it seems fine, but it shows e.g. Hello Optional "(name)" instead of Hello (name).
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var helloLabel: UILabel!
#IBOutlet weak var nameTextField: UITextField!
#IBOutlet weak var sayHelloButton: UIButton!
#IBAction func sayHelloAction(sender: AnyObject)
{
let name = nameTextField.text
if name!.isEmpty {
let alert = UIAlertController(title: "Error", message: "Please enter a name", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
} else {
helloLabel.text = "Hello \(name)!"
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
setupUI()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func setupUI() {
helloLabel.text = "Hello There!"
helloLabel.textColor = UIColor.blueColor()
helloLabel.textAlignment = NSTextAlignment.Center
nameTextField.placeholder = "Enter your name"
sayHelloButton.setTitle("Say Hello", forState: .Normal)
}
}
Can anyone help me, please?
Doms.
In Swift you have a type called Optional. This is used to express nullability. You need to do what is called unwraping the optional. I will discourage you from force unwrapping ! it will cause your app to crash. You can unwrap an optional value using the if let statement:
#IBAction func sayHelloAction(sender: AnyObject) {
if let name = nameTextField.text where !name.isEmpty {
helloLabel.text = "Hello \(name)"
} else {
let alert = UIAlertController(title: "Error", message: "Please enter a name", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}
}
I ran into this when I was just learning Swift myself, and it tends to pop out in all sorts of places. For instance, I couldn't understand why one of my tableview columns always said "0" instead of "1" or "2". It was in fact saying "O"ptional!
The simplest solution is to guard everything everywhere. That way the compiler knows you've checked that it's not nil, and "unwraps" the value for you. so instead of:
let name = nameTextField.text
just do a:
guard let name = nameTextField.text else { return }
Replace that return with something more appropriate. From that point on, name is the string and won't have the Optional(theThingYouReallyWanted) any more.
note: as I said at the start, this has a habit of showing up in weird places. If you bind Optionals into things like text fields or table columns, you'll see it when you don't expect it. I strongly suggest making getter/setter properties for all UI work, and using the guard to unwrap as above and instead of return hand back an empty string or something similar.
You get the Optional("") because the optional value is not unwrapped. You need to put a ! after the object and you won't get the Optional("") bit any more. I would show you the code but you haven't shown us the print() statement. I made some sample ones below that I think would replicate the problem, though I haven't tried them.
var value:String?
value = "Hello, World"
print("The Value Is \(value)") // Prints "The Value Is Optional(Hello, World)"
print("The Value Is \(value!)")// Prints "The Value Is Hello, World"