don't save if the textfield is empty - ios

I am working on a college project and I was having this problem that I don't know how to fix. When the user clicks on the Register button his information will be saved but if he didn't fill in the blanks he will get an error message. But the problem is that it will save an empty textfield in the CoreData. So I want to "Catch" that and give them an error without saving an empty textfield to the CoreData.
import UIKit
import CoreData
class ViewRegister: UIViewController {
#IBOutlet weak var txtName: UITextField!
#IBOutlet weak var txtUsername: UITextField!
#IBOutlet weak var txtPassword: UITextField!
#IBOutlet weak var txtPhone: UITextField!
#IBOutlet weak var txtAddress: UITextField!
#IBOutlet weak var txtCity: UITextField!
#IBAction func btnRegister(_ sender: Any) {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let newContact = NSEntityDescription.insertNewObject(forEntityName: "Users", into: context)
newContact.setValue(txtName.text, forKey: "name")
newContact.setValue(txtUsername.text, forKey: "username")
newContact.setValue(txtPassword.text, forKey: "password")
newContact.setValue(txtPhone.text , forKey: "phone")
newContact.setValue(txtAddress.text , forKey: "address")
newContact.setValue(txtCity.text , forKey: "city")
do{
try context.save()
print ("Saved")
}
catch{
print ("Error")
}
if txtCity.text == "" || txtAddress.text == "" || txtPhone.text == "" || txtPassword.text == "" || txtUsername.text == "" || txtName.text == ""
{
// Create the alert controller
let alert = UIAlertController(title: "Ops!!", message: "Please fill in the information", preferredStyle: .alert)
// Create the actions
let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.default) {
UIAlertAction in
NSLog("OK Pressed")
}
let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel) {
UIAlertAction in
NSLog("Cancel Pressed")
}
// Add the actions
alert.addAction(okAction)
alert.addAction(cancelAction)
// Present the controller
self.present(alert, animated: true, completion: nil)
}
else
{
txtName.text = ""
txtUsername.text = ""
txtPassword.text = ""
txtPhone.text = ""
txtAddress.text = ""
txtCity.text = ""
// Create the alert controller
let alert = UIAlertController(title: "Successfully Registered!", message: "Thank you for registering in our application", preferredStyle: .alert)
// Create the actions
let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.default) {
UIAlertAction in
NSLog("OK Pressed")
}
let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel) {
UIAlertAction in
NSLog("Cancel Pressed")
}
// Add the actions
alert.addAction(okAction)
alert.addAction(cancelAction)
// Present the controller
self.present(alert, animated: true, completion: nil)
}
}
}

I only can repeat the comment by #Lepidopteron: Why don't you call your contact initialization and save-call in your "else" code part?
Like this?
#IBAction func btnRegister(_ sender: Any) {
if txtCity.text == "" || txtAddress.text == "" || txtPhone.text == "" || txtPassword.text == "" || txtUsername.text == "" || txtName.text == ""
{
// Create the alert controller
let alert = UIAlertController(title: "Ops!!", message: "Please fill in the information", preferredStyle: .alert)
// Create the actions
let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.default) {
UIAlertAction in
NSLog("OK Pressed")
}
let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel) {
UIAlertAction in
NSLog("Cancel Pressed")
}
// Add the actions
alert.addAction(okAction)
alert.addAction(cancelAction)
// Present the controller
self.present(alert, animated: true, completion: nil)
}
else
{
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let newContact = NSEntityDescription.insertNewObject(forEntityName: "Users", into: context)
newContact.setValue(txtName.text, forKey: "name")
newContact.setValue(txtUsername.text, forKey: "username")
newContact.setValue(txtPassword.text, forKey: "password")
newContact.setValue(txtPhone.text , forKey: "phone")
newContact.setValue(txtAddress.text , forKey: "address")
newContact.setValue(txtCity.text , forKey: "city")
do{
try context.save()
print ("Saved")
}
catch{
print ("Error")
}
txtName.text = ""
txtUsername.text = ""
txtPassword.text = ""
txtPhone.text = ""
txtAddress.text = ""
txtCity.text = ""
// Create the alert controller
let alert = UIAlertController(title: "Successfully Registered!", message: "Thank you for registering in our application", preferredStyle: .alert)
// Create the actions
let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.default) {
UIAlertAction in
NSLog("OK Pressed")
}
let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel) {
UIAlertAction in
NSLog("Cancel Pressed")
}
// Add the actions
alert.addAction(okAction)
alert.addAction(cancelAction)
// Present the controller
self.present(alert, animated: true, completion: nil)
}
}

Related

debugPrint says "UAUTHENTICATED"

I am trying to link firebasse with stripe to my ios app.
The debugPrint in my code in the console says "UNAUTHENTICATED
This is my Viewontroller-
import UIKit
import FirebaseFirestore
import FirebaseAuth
import Stripe
import FirebaseFunctions
class SignUpViewController: UIViewController {
var paymentContext = STPPaymentContext()
#IBOutlet weak var email: UITextField!
#IBOutlet weak var password: UITextField!
#IBOutlet weak var passwordConfirm: UITextField!
#IBAction func signUpAction(_ sender: Any) {
if password.text != passwordConfirm.text {
let alertController = UIAlertController(title: "Password Incorrect", message: "Please re-type password", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
}
else{
Auth.auth().createUser(withEmail: email.text!, password: password.text!){
(user, error) in if error == nil {
}
else{
let alertController = UIAlertController(title: "Error", message: error?.localizedDescription, preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
}
}
}
Functions.functions().httpsCallable("createStripeUser").call(["email": email.text ?? ""]) {
(result, error) in
if let error = error {
debugPrint(error.localizedDescription)
return
}
self.dismiss(animated: true)
}
}
}
The debugPrint line in my code above "UNAUTHENTICATED" in the console as shown beolow:-
As you can see the customer is created in the FirebaseAuth as shown below:-
Also, the stripe customer is not created
How to sort it-out?
After edit suggested by Frank van Puffelen, viewcontroller code -
import UIKit
import FirebaseFirestore
import FirebaseAuth
import Stripe
import FirebaseFunctions
class SignUpViewController: UIViewController {
var paymentContext = STPPaymentContext()
#IBOutlet weak var email: UITextField!
#IBOutlet weak var password: UITextField!
#IBOutlet weak var passwordConfirm: UITextField!
#IBAction func signUpAction(_ sender: Any) {
if password.text != passwordConfirm.text {
let alertController = UIAlertController(title: "Password Incorrect", message: "Please re-type password", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
}
else{
Auth.auth().createUser(withEmail: email.text!, password: password.text!){ [self]
(user, error) in if error == nil {
// 👇
Functions.functions().httpsCallable("createStripeUser").call(["email": self.email.text ?? ""]) {
(result, error) in
if let error = error {
debugPrint(error.localizedDescription)
return
}
self.dismiss(animated: true)
}
}
else{
let alertController = UIAlertController(title: "Error", message: error?.localizedDescription, preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
}
}
}
}
}
That didnt help.
Code that needs to run after the user was created needs to be inside the completion handler for createUser(withEmail:, password:). So move the call httpsCallable("createStripeUser") into that block:
#IBAction func signUpAction(_ sender: Any) {
if password.text != passwordConfirm.text {
let alertController = UIAlertController(title: "Password Incorrect", message: "Please re-type password", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
}
else{
Auth.auth().createUser(withEmail: email.text!, password: password.text!){
(user, error) in if error == nil {
// 👇
Functions.functions().httpsCallable("createStripeUser").call(["email": email.text ?? ""]) {
(result, error) in
if let error = error {
debugPrint(error.localizedDescription)
return
}
self.dismiss(animated: true)
}
}
else{
let alertController = UIAlertController(title: "Error", message: error?.localizedDescription, preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
}
}
}
}

'hostViewController must not be nil on STPPaymentContext when calling pushPaymentOptionsViewController on it

This is my SignUpViewController:-
import UIKit
import Firebase
import Stripe
class SignUpViewController: UIViewController {
var paymentContext = STPPaymentContext()
#IBOutlet weak var email: UITextField!
#IBOutlet weak var password: UITextField!
#IBOutlet weak var passwordConfirm: UITextField!
#IBAction func signUpAction(_ sender: Any) {
if password.text != passwordConfirm.text {let alertController = UIAlertController(title: "Password Incorrect", message: "Please re-type password", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
}else{
Auth.auth().createUser(withEmail: email.text!, password: password.text!){ (user, error) in if error == nil {
self.performSegue(withIdentifier: "signupToHome", sender: self)
}
else{
let alertController = UIAlertController(title: "Error", message: error?.localizedDescription, preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
}
}
}
}
#IBAction func userIconClicked(_ sender: Any){
let userSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
let logout = UIAlertAction(title: "Logout", style: .default) { (action) in
// Logout
do {
try Auth.auth().signOut()
} catch {
debugPrint(error.localizedDescription)
}
}
let manageCards = UIAlertAction(title: "Manage Credit Cards", style: .default) { (action) in
// Display Stripe Widget
self.paymentContext.pushPaymentOptionsViewController()
}
let manageBanks = UIAlertAction(title: "Manage Bank Accounts", style: .default) { (action) in
// Manage Bank Accounts
}
let close = UIAlertAction(title: "Close", style: .cancel)
userSheet.addAction(manageCards)
userSheet.addAction(manageBanks)
userSheet.addAction(logout)
userSheet.addAction(close)
present(userSheet, animated: true)
}
func setupStripe() {
Wallet.instance.customerContext = STPCustomerContext(keyProvider: StripeApiClient())
let config = STPPaymentConfiguration.shared
paymentContext = STPPaymentContext(customerContext: Wallet.instance.customerContext,
configuration: config(),
theme: .default())
paymentContext.hostViewController = self
}
}
This what it is in the simulator:--
The "Button" on the right-hand-upper-corner is linked to "#IBAction func userIconClicked(_ sender: Any)". When I click on this button, the following shows up on the simulator: -
Now, when I click on "Manage Credit Cards", it shows error in the AppDelegate - - Thread 1: "hostViewController must not be nil on STPPaymentContext when calling pushPaymentOptionsViewController on it. Next time, set the hostViewController property first! as shown in the screenshot below:-
What am I doing wrong ?
Edit 1: after humnoz comment, I called "setupStripe()", still same error -
import UIKit
import Firebase
import Stripe
class SignUpViewController: UIViewController {
var paymentContext = STPPaymentContext()
#IBOutlet weak var email: UITextField!
#IBOutlet weak var password: UITextField!
#IBOutlet weak var passwordConfirm: UITextField!
#IBAction func signUpAction(_ sender: Any) {
if password.text != passwordConfirm.text {let alertController = UIAlertController(title: "Password Incorrect", message: "Please re-type password", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
}else{
Auth.auth().createUser(withEmail: email.text!, password: password.text!){ (user, error) in if error == nil {
self.performSegue(withIdentifier: "signupToHome", sender: self)
}
else{
let alertController = UIAlertController(title: "Error", message: error?.localizedDescription, preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
}
}
}
}
func viewDidLoad(_ animated: Bool) {
Auth.auth().addStateDidChangeListener { (auth, user) in
// If there is a user logged in, stay here on homeVC
// else, take them to the login page.
if user == nil {
let loginVC = LoginRegisterVC()
loginVC.modalPresentationStyle = .fullScreen
self.present(loginVC, animated: true)
} else {
UserManager.instance.getCurrentUser {
self.setupStripe()
}
}
}
}
#IBAction func userIconClicked(_ sender: Any){
let userSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
let logout = UIAlertAction(title: "Logout", style: .default) { (action) in
// Logout
do {
try Auth.auth().signOut()
} catch {
debugPrint(error.localizedDescription)
}
}
let manageCards = UIAlertAction(title: "Manage Credit Cards", style: .default) { (action) in
// Display Stripe Widget
self.paymentContext.pushPaymentOptionsViewController()
}
let manageBanks = UIAlertAction(title: "Manage Bank Accounts", style: .default) { (action) in
// Manage Bank Accounts
}
let close = UIAlertAction(title: "Close", style: .cancel)
userSheet.addAction(manageCards)
userSheet.addAction(manageBanks)
userSheet.addAction(logout)
userSheet.addAction(close)
present(userSheet, animated: true)
}
func setupStripe() {
Wallet.instance.customerContext = STPCustomerContext(keyProvider: StripeApiClient())
let config = STPPaymentConfiguration.shared
paymentContext = STPPaymentContext(customerContext: Wallet.instance.customerContext,
configuration: config(),
theme: .default())
paymentContext.hostViewController = self
}
}
This post helped me im my case - https://it.wenda123.org/question/stack/40711655/stripe-checkout-ios-integration-with-storyboards-in-swift-3

Swift 4 local variable value assignment

I am trying to recovery a value from firebase database and compare it with a UITextField value, in case of matching, I save it to a var that I will us. The problem is that the variable in question has a default value just when I use it.
Above I show my func code where the variable affected is "codeRecovered":
#IBAction func signUpAction(_ sender: AnyObject)
{
var codeRecovered: String = ""
if emailSignUpTextField.text == "" || self.secretCodeTextField.text == "" {
let alertController = UIAlertController(title: "Error", message: "Please enter your email, pin code and password", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
present(alertController, animated: true, completion: nil)
} else {
self.dbHandler = self.ref?.child("Companies").observe(.value, with: { (snapshot) in
for child in snapshot.children {
let snap = child as! DataSnapshot
let value = snap.value as! [String:String]
if let auxSecretCode = value["secretCode"]
{
if auxSecretCode == self.secretCodeTextField.text{
print("Value recovered OK(works fine): \(auxSecretCode)")
codeRecovered = auxSecretCode
print("Recovered value saved OK(works fine): \(codeRecovered)")
}
}
}
})
//Here codeRecovered is already ""
print("\(codeRecovered) is the recovered value(empty) and \(self.secretCodeTextField.text ?? "def") is the textField value")
if codeRecovered != self.secretCodeTextField.text{
let alertController = UIAlertController(title: "Error", message: "Please enter a correct pin code", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
present(alertController, animated: true, completion: nil)
}
//....
Async calls with sync result use....
#IBAction func signUpAction(_ sender: AnyObject)
{
var codeRecovered: String = ""
if emailSignUpTextField.text == "" || self.secretCodeTextField.text == "" {
let alertController = UIAlertController(title: "Error", message: "Please enter your email, pin code and password", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
present(alertController, animated: true, completion: nil)
} else {
self.dbHandler = self.ref?.child("Companies").observe(.value, with: { (snapshot) in
for child in snapshot.children {
let snap = child as! DataSnapshot
let value = snap.value as! [String:String]
if let auxSecretCode = value["secretCode"]
{
if auxSecretCode == self.secretCodeTextField.text{
print("Value recovered OK(works fine): \(auxSecretCode)")
codeRecovered = auxSecretCode
print("Recovered value saved OK(works fine): \(codeRecovered)")
}
}
}
//Here codeRecovered is already ""
print("\(codeRecovered) is the recovered value(empty) and \(self.secretCodeTextField.text ?? "def") is the textField value")
if codeRecovered != self.secretCodeTextField.text{
let alertController = UIAlertController(title: "Error", message: "Please enter a correct pin code", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
present(alertController, animated: true, completion: nil)
}
})
to use your codeRecovered in a sequence it must be within self.dbHandler = self.ref?.child("Companies").... block because it runs in async thread

Unknown Selector Issue

I am attempting to create a sign up page where people put such info as their email and desired password, after this is completed I want to switch to the next view controller however, I am getting the following error
[StudyBuddy.SignUpViewController signUpButton:]: unrecognized selector sent to instance 0x7fac5e061b80'
SignUpViewController
import UIKit
import Firebase
import CoreData
import CoreLocation
class SignUpViewController: UIViewController {
#IBOutlet weak var emailField: UITextField!
#IBOutlet weak var passwordField: UITextField!
#IBOutlet weak var confirmPasswordField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
if let user = FIRAuth.auth()?.currentUser {
}
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func signupButton(sender: AnyObject)
{
if self.emailField.text == "" || self.passwordField.text == "" {
let alertController = UIAlertController(title: "Oops!", message: "Please enter a valid username and password", preferredStyle: .Alert)
let defaultAction = UIAlertAction(title: "Ok", style: .Cancel, handler: nil)
self.presentViewController(alertController, animated: true, completion: nil)
}
else if self.confirmPasswordField.text != self.passwordField.text {
let passwordAlert = UIAlertController(title: "Oops!", message: "Passwords do not match", preferredStyle: .Alert)
let passwordAction = UIAlertAction(title: "Ok", style: .Cancel, handler: nil)
self.presentViewController(passwordAlert, animated: true, completion: nil)
}
else {
FIRAuth.auth()?.createUserWithEmail(emailField.text!, password: passwordField.text!, completion: {(user, error) in
if error == nil {
self.performSegueWithIdentifier("goToSignUp", sender: sender)
}
else {
let createAlert = UIAlertController(title: "There was a problem", message: "There was a problem creating your account, please check the information you provided and try again", preferredStyle: .Alert)
let createAction = UIAlertAction(title: "Ok", style: .Cancel, handler: nil)
self.presentViewController(createAlert, animated: true, completion: nil)
}
})
}
}
You need to change your signupButton method declaration with signUpButton because inside your declaration u is lower latter for up you need to change it with Up because method name and property name are case sensitive or else change to selector with this signupButton one where you are adding target for button.

NSUserDefault not being saved

I only want the alert to show up if the variable "genderDefault" has not been assigned yet.
This code is suppose to save the choice of the user:
func genderAlert()
{
let alertController = UIAlertController(title: "Quick Question", message: "What's your gender?", preferredStyle: UIAlertControllerStyle.Alert)
let okAction = UIAlertAction(title: "Male", style: UIAlertActionStyle.Default) {
UIAlertAction in
NSLog("Male Pressed")
self.genderDefault.setValue("male", forKey: "gender")
}
let cancelAction = UIAlertAction(title: "Female", style: UIAlertActionStyle.Default) {
UIAlertAction in
NSLog("Female Pressed")
self.genderDefault.setValue("female", forKey: "gender")
}
alertController.addAction(okAction)
alertController.addAction(cancelAction)
self.presentViewController(alertController, animated: true, completion: nil)
}
This is the if-statement that controls whether the alert shows up:
if(genderDefault != "male" || genderDefault != "female")
{
genderAlert()
}
Swift 3
let genderDefault = UserDefaults.standard
genderDefault.set(value: AnyObject?, forKey: String) // SET
genderDefault.object(forKey: String) // GET
Swift 2
let genderDefault = NSUserDefaults.standardUserDefaults()
genderDefault.setObject("female", forKey: "gender") // SET
if let gender = genderDefault.stringForKey("gender"){ // GET
if((gender as! String) != "male" || (gender as! String) != "female")
{
genderAlert()
}
}
What ever you do you have to set userDefaults.synchronize() at last so that userDefaults should come to know that now it has to save
let userDefaults = NSUserDefaults.standardUserDefaults()
userDefaults.setValue("female", forKey: "gender")
userDefaults.synchronize() // don't forget this!!!!

Resources