For some reason my firebase methods do things that make no sense to me. I want to login with a user and afterwards check on some data to make a decision. Both methods signIn() and getDocument() don't go beyond the curly brackets. If I set a breakpoint or step over the next point where it stops is outside the curly brackets. What am I doing wrong?
This is the whole code:
import Foundation
import Firebase
//#objc(LoginViewController)
class LoginViewController: UIViewController {
#IBOutlet weak var errorMessage: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBOutlet weak var emailField: UITextField!
#IBOutlet weak var passwordField: UITextField!
#IBAction func didTapEmailLogin(_ sender: UIButton) {
// Check if empty
guard emailField.text != nil, passwordField.text != nil else {
self.errorMessage.text = "Fields can't be empty."
return
}
// Log in
let email = emailField.text!
let password = passwordField.text!
guard login(with: email, with: password) else {
print("Login didn't work")
return
}
// Check if user has a group yet
guard userHasGroup() else {
print("Getting data didn't work")
return
}
}
func userHasGroup() -> Bool {
var succesful = true
let db = Firestore.firestore()
let userUid = Auth.auth().currentUser?.uid
let docRef = db.collection("users").document(userUid!)
docRef.getDocument { (document, _) in
if let document = document, document.exists {
// Test
print(document.data() as! [String: Any])
} else {
succesful = false
}
}
return succesful
}
func login(with email: String, with password: String) -> Bool {
var succesful = true
Auth.auth().signIn(withEmail: email, password: password) { (user, error) in
guard error == nil, user != nil else {
// There was an error.
self.errorMessage.text = "Email/password incorrect."
succesful = false
return
}
}
return succesful
}
}
This is the definition of async behaviour. The first time through your function all the code outside the closure is executed. Then when this async call to signIn returns the code inside the closure is executed.
The problem is the structure of your function. You can't reliably return a value from a function that contains a closure as the value won't be set when the function returns.
You need to change your function to use a completion handler.
I've posted a recent example of how to do this here Why aren't my Firebase Storage URLs uploading to Google Cloud Firestore?
So indeed it was an async problem.
This is how I made it work:
#IBAction func didTapEmailLogin(_ sender: UIButton) {
// Check if empty
guard emailField.text != nil, passwordField.text != nil else {
self.errorMessage.text = "Fields can't be empty."
return
}
let email = emailField.text!
let password = passwordField.text!
loginAsync(with: email, with: password) { (loginSuccesful) in
if loginSuccesful {
self.userHasGroupAsync(completionHandler: { (hasGroup) in
if hasGroup {
self.performSegue(withIdentifier: "fromLoginToHome", sender: self)
} else {
self.performSegue(withIdentifier: "fromLoginToCreateJoinGroup", sender: self)
}
})
}
}
}
func loginAsync(with email: String, with password: String, completionHandler: #escaping (Bool) -> ()) {
var succesful = true
Auth.auth().signIn(withEmail: email, password: password) {
(user, error) in
guard error == nil, user != nil else {
// There was an error.
self.errorMessage.text = "Email/password incorrect."
succesful = false
return
}
completionHandler(succesful)
}
}
func userHasGroupAsync(completionHandler: #escaping (Bool) -> ()) {
var hasGroup = false
let db = Firestore.firestore()
let userUid = Auth.auth().currentUser?.uid
let docRef = db.collection("users").document(userUid!)
docRef.getDocument { (document, _) in
if let document = document, document.exists {
let data: [String: Any] = document.data()!
let group = data["group"] as! String
if group != "" { hasGroup = true }
}
completionHandler(hasGroup)
}
}
Related
I've logged in with firebase in my iOS app and I have the Google Sheets API pod initialized in the podfile but I'm getting this error when I try to append data to my spreadsheet:
Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential.
Here is my spreadsheets code:
//
// SpredsheetsController.swift
// frcscout
//
// Created by Elliot Scher on 12/21/22
//
import UIKit
import GoogleAPIClientForREST
import GoogleSignIn
class SpreadsheetsController: UIViewController {
let utils = Utils()
let sheetService = GTLRSheetsService()
override func viewDidLoad() {
super.viewDidLoad()
sheetService.authorizer = GIDSignIn.sharedInstance.currentUser?.authentication.fetcherAuthorizer()
}
#IBAction func appendDataPressed(_ sender: UIButton) {
appendData()
}
#IBAction func specificCellPressed(_ sender: UIButton) {
sendDataToCell()
}
#IBAction func readDataPressed(_ sender: UIButton) {
readData()
}
#IBAction func readSheetsPressed(_ sender: UIButton) {
readSheets()
}
}
extension SpreadsheetsController {
func appendData() {
let spreadsheetId = K.sheetID
let range = "A1:Q"
let rangeToAppend = GTLRSheets_ValueRange.init();
let data = ["this", "is", "a", "test"]
rangeToAppend.values = [data]
let query = GTLRSheetsQuery_SpreadsheetsValuesAppend.query(withObject: rangeToAppend, spreadsheetId: spreadsheetId, range: range)
query.valueInputOption = "USER_ENTERED"
sheetService.executeQuery(query) { (ticket, result, error) in
if let error = error {
print("Error in appending data: \(error)")
} else {
print("Data sent: \(data)")
}
}
}
func sendDataToCell() {
let spreadsheetId = K.sheetID
let currentRange = "A5:B5" //Any range on the sheet, for instance: A5:B6
let results = ["this is a test"]
let rangeToAppend = GTLRSheets_ValueRange.init();
rangeToAppend.values = [results]
let query = GTLRSheetsQuery_SpreadsheetsValuesUpdate.query(withObject: rangeToAppend, spreadsheetId: spreadsheetId, range: currentRange)
query.valueInputOption = "USER_ENTERED"
sheetService.executeQuery(query) { (ticket, result, error) in
if let error = error {
print(error)
} else {
print("Sending: \(results)")
}
}
}
func readData() {
print("Getting sheet data...")
let spreadsheetId = K.sheetID
let range = "A1:Q"
let query = GTLRSheetsQuery_SpreadsheetsValuesGet
.query(withSpreadsheetId: spreadsheetId, range:range)
sheetService.executeQuery(query) { (ticket, result, error) in
if let error = error {
print(error)
return
}
guard let result = result as? GTLRSheets_ValueRange else {
return
}
let rows = result.values!
var stringRows = rows as! [[String]]
for row in stringRows {
stringRows.append(row)
print(row)
}
if rows.isEmpty {
print("No data found.")
return
}
print("Number of rows in sheet: \(rows.count)")
}
}
func readSheets() {
print("func findSpreadNameAndSheets executing...")
let spreadsheetId = K.sheetID
let query = GTLRSheetsQuery_SpreadsheetsGet.query(withSpreadsheetId: spreadsheetId)
sheetService.executeQuery(query) { (ticket, result, error) in
if let error = error {
print(error)
} else {
let result = result as? GTLRSheets_Spreadsheet
let sheets = result?.sheets
if let sheetInfo = sheets {
for info in sheetInfo {
print("New sheet found: \(String(describing: info.properties?.title))")
}
}
}
}
}
}
Here is my authentication code:
//
// AuthenticationViewModel.swift
// frcscout
//
// Created by Elliot Scher on 12/15/22.
//
import Foundation
import Firebase
import GoogleSignIn
class AuthenticationViewModel: ObservableObject {
var credential:AuthCredential? = nil
enum SignInState {
case signedIn
case signedOut
}
#Published var state: SignInState = .signedOut
func signIn() {
// 1
if GIDSignIn.sharedInstance.hasPreviousSignIn() {
GIDSignIn.sharedInstance.restorePreviousSignIn { [unowned self] user, error in
authenticateUser(for: user, with: error)
}
} else {
guard let clientID = FirebaseApp.app()?.options.clientID else { return }
let configuration = GIDConfiguration(clientID: clientID)
guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene else { return }
guard let rootViewController = windowScene.windows.first?.rootViewController else { return }
GIDSignIn.sharedInstance.signIn(with: configuration, presenting: rootViewController) { [unowned self] user, error in
authenticateUser(for: user, with: error)
}
}
}
private func authenticateUser(for user: GIDGoogleUser?, with error: Error?) {
if let error = error {
print(error.localizedDescription)
return
}
guard let authentication = user?.authentication, let idToken = authentication.idToken else { return }
credential = GoogleAuthProvider.credential(withIDToken: idToken, accessToken: authentication.accessToken)
Auth.auth().signIn(with: credential!) { [unowned self] (_, error) in
if let error = error {
print(error.localizedDescription)
} else {
self.state = .signedIn
}
}
}
func signOut() {
GIDSignIn.sharedInstance.signOut()
do {
try Auth.auth().signOut()
state = .signedOut
} catch {
print(error.localizedDescription)
}
}
func getCredential() -> AuthCredential {
return credential!
}
}
I think I need an oauth2 token but I'm not sure how to get it from firebase. Could someone help me resolve this issue? Thanks!!
Resolved:
I had to put this line:
sheetService.authorizer = GIDSignIn.sharedInstance.currentUser?.authentication.fetcherAuthorizer()
at the beginning of each method.
Here is the code from sign up view controller
import UIKit
import Firebase
class SignUpViewController: UIViewController {
#IBOutlet weak var userNameTextField: UITextField!
#IBOutlet weak var emailTextField: UITextField!
#IBOutlet weak var passwordTextField: UITextField!
#IBOutlet weak var errorLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
userNameTextField.backgroundColor = .clear
userNameTextField.layer.cornerRadius = 27
userNameTextField.layer.borderWidth = 1
userNameTextField.layer.borderColor = UIColor.systemGreen.cgColor
emailTextField.backgroundColor = .clear
emailTextField.layer.cornerRadius = 27
emailTextField.layer.borderWidth = 1
emailTextField.layer.borderColor = UIColor.systemGreen.cgColor
passwordTextField.backgroundColor = .clear
passwordTextField.layer.cornerRadius = 27
passwordTextField.layer.borderWidth = 1
passwordTextField.layer.borderColor = UIColor.systemGreen.cgColor
}
And here is the code that must be executed after pressing the sign up button, but if I fill in password and email but not the username it throws an error and it still saves the data without username and after I try to sign up with the same email it says that this email already exists, even though username was empty
#IBAction func signupPressed(_ sender: UIButton) {
if let email = emailTextField.text, let password = passwordTextField.text {
Auth.auth().createUser(withEmail: email, password: password) { authResult, error in
if let e = error {
self.errorLabel.text = e.localizedDescription
} else if self.userNameTextField.text == "" || self.userNameTextField.text!.count <= 3 {
self.errorLabel.text = "Please enter a valid username"
} else {
//Navigate to the ChatViewController
let db = Firestore.firestore()
db.collection("users").addDocument(data: ["username": self.userNameTextField.text!, "uid": authResult!.user.uid]) { (error) in
if let e = error {
self.errorLabel.text = e.localizedDescription
}
}
self.performSegue(withIdentifier: "goToMap", sender: self)
}
}
}
}
}
You are checking for a username after you have created an account for the user, this is why you have an account regardless of having a username.
You should probably check that the username exists before creating the account. Using a guard let would allow you to check the username matches your criteria.
#IBAction func signupPressed(_ sender: UIButton) {
// check that the username exists and that it is of a valid length
guard let username = self.userNameTextField.text, username.count > 3 else {
self.errorLabel.text = "Please enter a valid username"
return
}
if let email = emailTextField.text, let password = passwordTextField.text {
Auth.auth().createUser(withEmail: email, password: password) { authResult, error in
if let e = error {
self.errorLabel.text = e.localizedDescription
} else {
//Navigate to the ChatViewController
let db = Firestore.firestore()
db.collection("users").addDocument(data: ["username": username, "uid": authResult!.user.uid]) { (error) in
if let e = error {
self.errorLabel.text = e.localizedDescription
}
}
// This will navigate the user regardless of whether the
// database update was successful or not.
// You may want to reconsider this, and handle it in the above closure.
self.performSegue(withIdentifier: "goToMap", sender: self)
}
}
}
}
You also do not show any checks for email or password. You may wish to consider adding them as well. This is how I would fully refactor your code with checks for email and password, plus moving the performSegue call so that it only occurs if you do not get an error from adding the username.
#IBAction func signupPressed(_ sender: UIButton) {
// check that the username exists and that it is of a valid length
guard let username = self.userNameTextField.text, username.count > 3 else {
self.errorLabel.text = "Please enter a valid username"
return
}
guard let password = passwordTextField.text else {
self.errorLabel.text = "Please enter a valid password"
return
}
guard let email = emailTextField.text else {
self.errorLabel.text = "Please enter a valid email"
return
}
Auth.auth().createUser(withEmail: email, password: password) { authResult, error in
if let e = error {
self.errorLabel.text = e.localizedDescription
} else {
//Navigate to the ChatViewController
let db = Firestore.firestore()
db.collection("users").addDocument(data: ["username": username, "uid": authResult!.user.uid]) { (error) in
if let e = error {
// You may not want to show this error to the user but you should still show a "sanitised" error so that it doesn't leak information.
self.errorLabel.text = e.localizedDescription
} else {
self.performSegue(withIdentifier: "goToMap", sender: self)
}
}
}
}
}
In the code if let email = emailTextField.text, let password = passwordTextField.text you are checking if the string reference is not nil. You also want to know if this string is not equal to "".
In this case, we can use the convenience getter: isEmpty.
Final code example:
#IBAction func signupPressed(_ sender: UIButton) {
if let email = emailTextField.text, let password = passwordTextField.text {
guard !email.isEmpty, !password.isEmpty else { return }
Auth.auth().createUser(withEmail: email, password: password) { authResult, error in
if let e = error {
self.errorLabel.text = e.localizedDescription
} else if self.userNameTextField.text == "" || self.userNameTextField.text!.count <= 3 {
self.errorLabel.text = "Please enter a valid username"
} else {
//Navigate to the ChatViewController
let db = Firestore.firestore()
db.collection("users").addDocument(data: ["username": self.userNameTextField.text!, "uid": authResult!.user.uid]) { (error) in
if let e = error {
self.errorLabel.text = e.localizedDescription
}
}
self.performSegue(withIdentifier: "goToMap", sender: self)
}
}
}
}
}
I'm trying to sign up users with Firebase auth. When a user signs up, I'd like them to be added to my Users collection in Firestore as well as the Users authorization section.
The createUser(withEmail: ...) method works every time. However, my db.collection("users").document(user.id).setData([..] method will only be called if I press the sign up button twice, and at that point the createUser(withEmail ...) method gets called again. Here's the relevant code
SignupViewController.swift
#IBAction func signupButtonTapped(_ sender: UIButton) {
// user: User() defined here
usersHelper.signup(user: user, password: password) { result in
// This closure is only executed on the second press
guard let user = result as? Firebase.User else {
let error = result as? Error
self.handleSignupError(error!)
return
}
self.performSegue(withIdentifier: "ShowGroupsFromSignupSegue", sender: self)
}
}
UsersHelper.Swift
func signup(user: User, password: String, completion: #escaping (_ result: Any?) -> Void) {
let userDispatchGroup = DispatchGroup()
var signupError: Error? = nil
var dbError: Error? = nil
var firebaseUser: Firebase.User? = nil
userDispatchGroup.enter()
usersDataModel.signupUser(user: user, password: password) { result in
// Completion handler
if result as? Error != nil {
signupError = result as? Error
} else {
// Got the user
firebaseUser = result as? Firebase.User
}
userDispatchGroup.leave()
}
userDispatchGroup.enter()
usersDataModel.create(user: user) { err in
// This will only execute if signUp is called twice
if let result = err as? Error {
print("Error msg: \(result.localizedDescription)")
dbError = result
}
print("!Created db user")
userDispatchGroup.leave()
}
userDispatchGroup.notify(queue: .main) {
print("!dispatch group completed successfully")
if (signupError == nil && dbError == nil) {
completion(firebaseUser)
} else {
signupError != nil ? completion(signupError) : completion(dbError)
}
}
}
UsersDataModel.swift
func signupUser(user: User, password: String, _ completion: #escaping (_ err: Any? ) -> Void) {
// Create user in Auth & create DB entry
Auth.auth().createUser(withEmail: user.email, password: password) { (authResult, err) in
if let err = err {
print("Error creating user \(err)")
completion(err)
} else {
print("User signed up successfully")
completion(authResult) // completion called with User
}
}
}
func create(user: User, _ completion: #escaping (_ result: Any?) -> Void) {
// userData dictionary created here
db.collection("users").document(user.ID).setData(userData) { err in
if let err = err {
print("There was an error creating the user \(err)")
completion(err)
} else {
print("!User created in db successfully!")
completion(nil)
}
}
}
Any help is greatly appreciated! Thank you all in advance
I've resolved the error. I ended up nesting the second network call in order to:
Get the uid from the firestore who was authenticated
Not break firestore rules about writing to the database w/o an authorized uid
My UsersHelper.swift file now looks like
func signup(user: User, password: String, completion: #escaping (_ result: Any?) -> Void) {
let userDispatchGroup = DispatchGroup()
var signupError: Error? = nil
var dbError: Error? = nil
var firebaseUser: Firebase.User? = nil
userDispatchGroup.enter()
usersDataModel.signupUser(user: user, password: password) { result in
// Completion handler
if result as? Error != nil {
// there was an error?
print("Error: \(result)")
signupError = result as? Error
} else {
// Got the user
firebaseUser = result as? Firebase.User
// Create user entry in DB
user.ID = firebaseUser!.uid
self.usersDataModel.create(user: user) { err in
// Completion handler
if let err = err as? Error {
dbError = err
}
userDispatchGroup.leave()
print("Done")
}
}
}
userDispatchGroup.notify(queue: .main) {
print("!dispatch group completed successfully")
if (signupError == nil && dbError == nil) {
completion(firebaseUser)
} else {
signupError != nil ? completion(signupError) : completion(dbError)
}
}
}
I'm writing some code for a login page where we take a username and find the associated password. Temporarily I've said "if email exists under username, complete segue". However when I call the method getEmail which checks for email, it never seems to exit properly with a full email address. print(email) returns the right email address so I know I've retrieved it and it's correct. I never seem to make it out of the method though. Really stuck here! Heres my code:
func getEmail(name: String) -> String{
var email = ""
ref = Database.database().reference()
self.ref.child("Users").child(name).observeSingleEvent(of: .value, with: { (snapshot) in
if let user = snapshot.value as? [String:Any] {
print("email retrieved");
email = user["email"] as! String;
print(email)
return;
}
else{
print("email could not be retrieved from the user.");
}
}){ (error) in
print("Could not retrieve object from database because: ");
print((Any).self);
}
return email;
}
func validate(){
if(Username.text == ""){
EmptyStringAlert();
}
let email = getEmail(name: Username.text!);
print(email)
if(email == ""){
return;
}
performSegue(withIdentifier: "LoginSuccess", sender: nil)
}
The call to Firebase is asynchronous, so you have to use completion in your function to get the data. Try something like this:
func getEmail(name: String, completion: #escaping (Bool, Any?, Error?) -> Void) {
var email = ""
ref = Database.database().reference()
self.ref.child("Users").child(name).observeSingleEvent(of: .value, with: { (snapshot) in
if let user = snapshot.value as? [String:Any] {
email = user["email"] as! String
completion(true, email, nil)
}
else {
completion(false, nil, nil)
}
}){ (error) in
completion(false, nil, error)
}
}
func validate(){
if(Username.text == ""){
EmptyStringAlert();
}
getEmail(name: Username.text!) { (success, response, error) in
guard success, let email = response as? String else {
print(error ?? "Failed getEmail..")
return
}
if(email == "") {
return
}
performSegue(withIdentifier: "LoginSuccess", sender: nil)
}
}
I've been trying to figure this problem out for a few days and can't seem to find a solution that works.
The problem is: When I try to create an account in my app, it automatically creates an account without entering any information. So basically the user puts no info and the account is still being created.
I'm currently using Firebase
Here is the code for that View:
import UIKit
import Firebase
class createAccountVC: UIViewController {
private let RIDER_SEGUE = "createAccountSegue"
#IBOutlet weak var emailTextField: UITextField!
#IBOutlet weak var passwordTextField: UITextField!
#IBOutlet weak var confirmPasswordTextField: UITextField!
#IBOutlet weak var createAccountButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
createAccountButton.titleLabel?.numberOfLines = 2
createAccountButton.titleLabel?.lineBreakMode = NSLineBreakMode.byWordWrapping
}
private func alertTheUser(title: String, message: String) {
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
let ok = UIAlertAction(title: "OK", style: .default, handler: nil)
alert.addAction(ok)
present(alert, animated: true, completion: nil)
}
#IBAction func signUp(_ sender: AnyObject) {
if emailTextField.text != "" && passwordTextField.text != "" && confirmPasswordTextField.text != "" {
AuthProvider.Instance.signUp(withEmail: emailTextField.text!, password: passwordTextField.text!, loginHandler: { (message) in
if message != nil {
self.alertTheUser(title: "Problem with creating a new user.", message: message!)
} else {
GroomrHandler.Instance.rider = self.emailTextField.text!
self.saveUserInfo(email: self.emailTextField.text!, password: self.passwordTextField.text!)
self.emailTextField.text = ""
self.passwordTextField.text = ""
self.confirmPasswordTextField.text = ""
//self.performSegue(withIdentifier: self.RIDER_SEGUE, sender: nil)
// save password to keychain
}
})
} else {
alertTheUser(title: "Email and password are required.", message: "Please enter email and password in the text fields.")
}
}
func saveUserInfo(email: String, password: String) {
//save login info in app
UserDefaults.standard.set(email, forKey: "email")
}
}
Thank you in advance! Don't flame me, I'm still learning XD
EDIT: Here is the AuthProvider File:
import Foundation
import Firebase
typealias LoginHandler = (_ msg: String?) -> Void
struct LoginErrorCode {
static let INVALID_EMAIL = "Invalid email address, please provide a real email address."
static let WRONG_PASSWORD = "Wrong password, please enter the correct password."
static let PROBLEM_CONNECTING = "Problem connecting to database, please try later."
static let USER_NOT_FOUND = "User not found, please register."
static let EMAIL_ALREADY_IN_USE = "Email already in use, please use another email."
static let WEAK_PASSWORD = "Password should be at least 6 characters long."
}
class AuthProvider {
private static let _instance = AuthProvider()
static var Instance: AuthProvider {
return _instance
}
func login(withEmail: String, password: String, loginHandler: LoginHandler?) {
Auth.auth().signIn(withEmail: withEmail, password: password, completion: { (user, error) in
if error != nil {
self.handleErrors(err: error! as NSError, loginHandler: loginHandler)
} else {
loginHandler?(nil)
}
})
} // login func
func signUp(withEmail: String, password: String, loginHandler: LoginHandler?) {
Auth.auth().createUser(withEmail: withEmail, password: password, completion: { (user, error) in
if error != nil {
self.handleErrors(err: error! as NSError, loginHandler: loginHandler)
} else {
if user?.uid != nil {
// login the user
self.login(withEmail: withEmail, password: password, loginHandler: loginHandler)
}
}
})
} // sign up func
func logOut() -> Bool {
if Auth.auth().currentUser != nil {
do {
try Auth.auth().signOut()
return true
} catch {
return false
}
}
return true
}
private func handleErrors(err: NSError, loginHandler: LoginHandler?) {
if let errCode = AuthErrorCode(rawValue: err.code) {
switch errCode {
case .wrongPassword:
loginHandler?(LoginErrorCode.WRONG_PASSWORD)
break
case .invalidEmail:
loginHandler?(LoginErrorCode.INVALID_EMAIL)
break
case .userNotFound:
loginHandler?(LoginErrorCode.USER_NOT_FOUND)
break
case .emailAlreadyInUse:
loginHandler?(LoginErrorCode.EMAIL_ALREADY_IN_USE)
break
case .weakPassword:
loginHandler?(LoginErrorCode.WEAK_PASSWORD)
break
default:
loginHandler?(LoginErrorCode.PROBLEM_CONNECTING)
break
}
}
}
} // class
I had some experience in registering users, here is my code, you may try it. Hope that it helps.
This in User object:
Auth.auth().createUser(withEmail: email, password: password, completion: { (user, error) in
if error == nil {
user?.sendEmailVerification(completion: nil)
let storageRef = Storage.storage().reference().child("usersProfilePics").child(user!.uid)
let imageData = UIImageJPEGRepresentation(profilePic, 0.1)
storageRef.putData(imageData!, metadata: nil, completion: { (metadata, err) in
if err == nil {
let path = metadata?.downloadURL()?.absoluteString
let values = ["name": withName, "email": email, "profilePicLink": path!]
Database.database().reference().child("users").child(userType).child((user?.uid)!).child("credentials").updateChildValues(values, withCompletionBlock: { (errr, _) in
if errr == nil {
let userInfo = ["email" : email, "password" : password, "type" : userType]
UserDefaults.standard.set(userInfo, forKey: "userInformation")
completion(true)
}
})
}
})
}
else {
completion(false)
}
})
Here I am calling method of User object:
User.registerUser(withName: self.registerNameField.text!, email: self.registerEmailField.text!, password: self.registerPasswordField.text!, profilePic: self.profilePicView.image!, forUserType: UserType.psychologist) { [weak weakSelf = self] (status) in
DispatchQueue.main.async {
weakSelf?.showLoading(state: false)
for item in self.inputFields {
item.text = ""
}
if status == true {
weakSelf?.pushTomainView()
weakSelf?.profilePicView.image = UIImage.init(named: "profile pic")
} else {
for item in (weakSelf?.waringLabels)! {
item.isHidden = false
}
}
}
}
var abcd: String?
if abcd != "" {
print("hello")
}
The above code prints hello in the console. Similar issue is happening in your code. condition abcd != "" only test for empty, not nil. You should first unwrap all textfield text, then check for isEmpty, and create account.
#IBAction func signUp(_ sender: AnyObject) {
guard let email = emailTextField.text,
let password = passwordTextField.text,
let confirmPassword = confirmPasswordTextField.text,
email != "",
password != "",
confirmPassword != "" else {
alertTheUser(title: "Email and password are required.", message: "Please enter email and password in the text fields.")
}
AuthProvider.Instance.signUp(withEmail: email, password: password, loginHandler: { (message) in
if message != nil {
self.alertTheUser(title: "Problem with creating a new user.", message: message!)
} else {
GroomrHandler.Instance.rider = email
self.saveUserInfo(email: email, password: password)
self.emailTextField.text = ""
self.passwordTextField.text = ""
self.confirmPasswordTextField.text = ""
//self.performSegue(withIdentifier: self.RIDER_SEGUE, sender: nil)
// save password to keychain
}
})
}