I think i have been coding for to many hours and i am getting delirious. I need a second eye to view my obvious problems.
-My function called ( #IBAction func SignIn ) at the bottom of the code ends after a single click. I click once works fine, click twice the code gets terminated and is done. How can I re-iterate this function so I can have it keep going every time I click the IB action button.
import UIKit
import Firebase
import FirebaseDatabase
import KeychainSwift
class SignUpController: UIViewController {
//Variable List
var ref = FIRDatabase.database().reference() //Data Base Initialization
public var validPassword = false //Both passwords match
//Represent Red or Green password Image
#IBOutlet weak var myImageView: UIImageView!
//INPUT - User Input from UI Text Fields
#IBOutlet weak var emailField: UITextField!
#IBOutlet weak var passwordField: UITextField!
#IBOutlet weak var passwordConfirmField : UITextField!
#IBOutlet weak var usernameField : UITextField!
#IBOutlet weak var nameField : UITextField!
/****************************View Loads*****************************/
override func viewDidLoad() {
super.viewDidLoad()
ref = FIRDatabase.database().reference()
myImageView.image = UIImage(named: "confirmPaswordRed")
}
//PROCESS - Checks is user has already been logged in
override func viewDidAppear(_ animated: Bool) {
let currentUser = FIRAuth.auth()?.currentUser
if currentUser != nil {
performSegue(withIdentifier: "SignIn", sender: nil)
}
}
/******************************************************************/
/****************************Functions*****************************/
func CompleteSignIn(id: String){
let keyChain = DataService().keyChain
keyChain.set(id , forKey: "uid")
}
//Send all data text fields to Firebase Database
func sendToFirebaseDatabase(userID : String) {
let name : String = self.nameField.text!
let username : String = self.usernameField.text!
let userEmail : String = self.emailField.text!
let userPassword : String = self.passwordField.text!
self.ref.child("Users").child(userID).setValue(["Name": name, "Username": username, "Email": userEmail, "Password" : userPassword])
}
//Determines Red or Green password validation
#IBAction func passwordConfirmImage(_ sender: UITextField) {
let userConfirmPassword : String? = self.passwordConfirmField.text!
let userPassword : String? = self.passwordField.text!
if (userPassword == userConfirmPassword) && (userPassword != "") {
validPassword = true
let greenImage = UIImage(named: "confirmPasswordGreen")
myImageView.image = greenImage
print("Function entry test")
}else {
myImageView.image = UIImage(named: "confirmPaswordRed")
validPassword = false
}
}
/******************************************************************/
/****************************IBACTIONS*****************************/
//If SignUp button is pressed user will be directed to sign up page
#IBAction func LoginPressed(_ sender: Any) {
self.performSegue(withIdentifier: "BackToLogin", sender: nil)
}
/*Sign In Action: If both password and email contain text lets put them into string variables
called email & password. Creates user and authorizes sign in */
#IBAction func SignIn(_ sender: Any){
if let email = emailField.text, let password = passwordField.text {
FIRAuth.auth()?.signIn(withEmail: email, password: password) { (user, error) in
if ((error == nil) && (self.validPassword) == true) {
self.CompleteSignIn(id: user!.uid) //Completes Database Sign in
print("Sign in Test")
self.performSegue(withIdentifier: "SignIn", sender: nil)
} else {
FIRAuth.auth()?.createUser(withEmail: email, password: password) { (user, error) in
if ((error == nil) && (self.validPassword) == false) {
Alerts().invalidSignUpAlert(sender: self) //Alert for invalid email & Password
print("cant sign in user") //Programmer Debugging
} else {
if self.validPassword == true{
let userID : String = user!.uid //initialize userId String
self.sendToFirebaseDatabase(userID: userID) //Call sendToFirebaseDatabase
self.performSegue(withIdentifier: "SignIn", sender: nil) //goto Login Page
}
}
}
}
}
}
}
}
Related
I would like some help with the coding on how to store data into a specific user after the user have successfully logged in. Below are the codes for the page where user can input the details of their new readings.
import UIKit
import Firebase
import FirebaseAuth
import FirebaseFirestore
class NewBookViewController: UIViewController {
#IBOutlet weak var bookTitleTextField: UITextField!
#IBOutlet weak var bookAuthorTextField: UITextField!
#IBOutlet weak var bookSummaryTextField: UITextField!
#IBOutlet weak var ratingController: UIView!
#IBOutlet weak var newBookCancelButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
}
func validateFields() -> String? {
if
bookTitleTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) == "" ||
bookAuthorTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) == "" ||
bookSummaryTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) == "" {
return "Please fill in all the fields."
}
return nil
}
#IBOutlet weak var newBookSaveButton: UIButton!
var ref = Firestore.firestore()
#IBAction func newBookSaveButtonTapped(_ sender: Any) {
let uid = Auth.auth().currentUser?.uid
self.ref?.child("new reading").child(uid).setValue(post)
func post() {
let bookTitleTextField = "bookTitle"
let bookAuthorTextField = "bookAuthor"
let bookSummaryTextField = "bookSummary"
let post : [String : AnyObject] = [ "bookTitle" : bookTitleTextField as AnyObject, "bookAuthor" : bookAuthorTextField as AnyObject, "bookSummary" : bookSummaryTextField as AnyObject]
}
this is the successful user sign up on cloud firestore. after the user have logged in, I wanted to add those 3 data (title, author, summary) FOR the specific user.
It looks like you're close. Right now, you aren't returning anything from post, though. I think you also mean to be getting the text values from each UITextField instead of just declaring Strings with the names of the fields.
#IBAction func newBookSaveButtonTapped(_ sender: Any) {
guard let uid = Auth.auth().currentUser?.uid else {
//handle your error here
return
}
self.ref?.child("new reading").child(uid).setValue(post())
}
func post() -> [String:String] {
return ["bookTitle" : bookTitleTextField.text ?? "",
"bookAuthor" : bookAuthorTextField.text ?? "",
"bookSummary" : bookSummaryTextField.text ?? ""]
}
You should take a much safer approach to handling the user's ID and the values of the text fields. Here, the data is only written to the database if the user is logged in and all 3 of the text fields have strings in them. I don't know what collection you intended to place this document in so I went with what you wrote but I suspect it isn't right.
class NewBookViewController: UIViewController {
private let db = Firestore.firestore()
#IBAction func newBookSaveButtonTapped(_ sender: Any) {
guard let uid = Auth.auth().currentUser?.uid,
let data = bookData() else {
return
}
db.collection("new reading").document(uid).setData(data)
}
// This returns an optional dictionary (nil when the data is incomplete).
// This is entirely optional (pun) but I suspect you don't want
// empty fields in these database documents.
func bookData() -> [String: Any]? {
guard let title = bookTitleTextField.text,
let author = bookAuthorTextField.text,
let summary = bookSummaryTextField.text else {
return nil
}
let data: [String: Any] = [
"bookTitle": title,
"bookAuthor": author,
"bookSummary": summary
]
return data
}
}
This question already has answers here:
"Value of type 'AuthDataResult' has no member 'uid'" error
(3 answers)
Closed 1 year ago.
how's everyone? I hope you're safe and well!
I'm studying SWIFT and problem came across and honestly I don't have a clue i how to solve it. Can any one help me?
Here is the code bellow:
import UIKit
import Firebase
class CreateUserVC: UIViewController {
#IBOutlet weak var emailTxt: UITextField!
#IBOutlet weak var passwordTxt: UITextField!
#IBOutlet weak var userNameTxt: UITextField!
#IBOutlet weak var createBtn: UIButton!
#IBOutlet weak var cancelBtn: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
createBtn.layer.cornerRadius = 10
cancelBtn.layer.cornerRadius = 10
// Do any additional setup after loading the view.
}
#IBAction func createUserTapped(_ sender: Any) {
guard let email = emailTxt.text,
let password = passwordTxt.text,
let userName = userNameTxt.text else { return }
Auth.auth().createUser(withEmail: "", password: "", completion: { (user, error) in
if let error = error {
debugPrint("Error creating user: \(error.localizedDescription)")
}
let changeRequest = user.profileChangeRequest()
changeRequest?.displayName = userName
changeRequest?.commitChanges(completion: {(error) in
})
})
}
#IBAction func cancelTapped(_ sender: Any) {
}
}
enter image description here
The completion block of Auth.auth.createUser isn't invoked with a User object but with an optional AuthDataResult object. So you need to check that the operation was successful by checking AuthDataResult isn't nil, retrieve the user object from it, then start your profileChangeRequest:
Auth.auth().createUser(withEmail: "", password: "", completion: { (result, error) in
guard let user = result?.user else {
if let error = error {
debugPrint("Error creating user: \(error.localizedDescription)")
} else {
debugPrint("Error creating user: unknown error")
}
return
}
let changeRequest = user.profileChangeRequest()
changeRequest?.displayName = userName
changeRequest?.commitChanges(completion: {(error) in
})
})
I have made an sign up and also login and it works! but now I want to edit the data in the Firebase. Can anyone help me how to do it? Thanks you
Here the Sign Up View Controller
import UIKit
import FirebaseAuth
import FirebaseFirestore
class SignupViewController: UIViewController {
#IBOutlet weak var FirstNameTextfield: UITextField!
#IBOutlet weak var LastNameTextfield: UITextField!
#IBOutlet weak var EmailTextField: UITextField!
#IBOutlet weak var PasswordTextfield: UITextField!
#IBOutlet weak var SignUpButton: UIButton!
#IBOutlet weak var ErrorLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
setUpElements()
}
func setUpElements(){
ErrorLabel.alpha = 0
}
func validateFields()->String? {
//check that all the fields are fill
if FirstNameTextfield.text?.trimmingCharacters(in: .whitespacesAndNewlines) == "" || LastNameTextfield.text?.trimmingCharacters(in: .whitespacesAndNewlines) == "" || EmailTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) == "" || PasswordTextfield.text?.trimmingCharacters(in: .whitespacesAndNewlines) == ""
{
return "Please fill up all the Fields"
}
//check the password if the password is secure
let cleanedPassword = PasswordTextfield.text!.trimmingCharacters(in: .whitespacesAndNewlines)
if Utilities.isPasswordValid(cleanedPassword) == false{
return "Please enter at least 8 characters, with a number and characteristic symbol"
}
return nil
}
#IBAction func SignUpTap(_ sender: Any) {
let error = validateFields()
if error != nil{
showError(message: error!)
}
else {
let FirstName = FirstNameTextfield.text!.trimmingCharacters(in: .whitespacesAndNewlines)
let LastName = LastNameTextfield.text!.trimmingCharacters(in: .whitespacesAndNewlines)
let Email = EmailTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
let Password = PasswordTextfield.text!.trimmingCharacters(in: .whitespacesAndNewlines)
Auth.auth().createUser(withEmail: Email, password: Password) { (result, err) in
if err != nil{
self.showError(message: "Error creating the user")
}
else {
let db = Firestore.firestore()
db.collection("users").addDocument(data:["FirstName":FirstName, "LastName":LastName, "uid": result!.user.uid]) { (Error) in
if error != nil{
self.showError(message: "Cannot saving user data" )
}
}
self.transitionToHomePage()
}
}
}
}
func showError( message:String){
ErrorLabel.text = message
ErrorLabel.alpha = 1
}
func transitionToHomePage(){
let TabHomeViewController = storyboard?.instantiateViewController(identifier: Constrants.Storyboard.TabHomeViewController) as? TabHomeViewController
view.window?.rootViewController = TabHomeViewController
view.window?.makeKeyAndVisible()
}
}
Here my login VC
#IBAction func LoginTap(_ sender: Any) {
let Email = EmailTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
let Password = PasswordTextfield.text!.trimmingCharacters(in: .whitespacesAndNewlines)
Auth.auth().signIn(withEmail: Email, password: Password) { (result, error) in
if error != nil{
self.ErrorLabel.text = error!.localizedDescription
self.ErrorLabel.alpha = 1
}
else{
let TabHomeViewController = self.storyboard?.instantiateViewController(identifier: Constrants.Storyboard.TabHomeViewController) as? UITabBarController
self.view.window?.rootViewController = TabHomeViewController
self.view.window?.makeKeyAndVisible()
}
And here my Account View Controller
import UIKit
import FirebaseAuth
import FirebaseFirestore
import Firebase
class AccountViewController: UIViewController {
#IBOutlet weak var FNameTextField: UITextField!
#IBOutlet weak var LNameTextField: UITextField!
#IBOutlet weak var EmailTextField: UITextField!
#IBOutlet weak var PasswordTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func logoutbutton(_ sender: Any) {
do{
try Auth.auth().signOut()
performSegue(withIdentifier: "signout", sender: nil)
}
catch{
print(error)
}
}
}
You can use this function:
func updateFirestoreUserProfile(uid: String, data: [String:Any]) {
Firestore.firestore().collection("users").document(uid).updateData(data) { err in
if let err = err {
print("Error updating document: \(err) ")
}
else {
print("Document successfully updated")
}
}
}
You can use the function like this:
let data = [
"FirstName": name,
"LastName": surname
]
updateFirestoreUserProfile(uid: user.uid, data: data)
Function moveToHome gives error when stating the viewcontroller class. Use of undeclared type 'HomeViewController'. I set the class of the view controller to HomeViewController but it is not being recognized.
import Foundation
import UIKit
import Firebase
import SwiftKeychainWrapper
import FirebaseAuth
import FirebaseFirestore
class SignUpEmail: UIViewController {
#IBOutlet weak var Email: UITextField!
#IBOutlet weak var Password: UITextField!
#IBOutlet weak var Firstname: UITextField!
#IBOutlet weak var Lastname: UITextField!
#IBOutlet weak var City: UITextField!
#IBOutlet weak var Street: UITextField!
#IBOutlet weak var Gender: UITextField!
#IBOutlet weak var SignupButton: UIButton!
#IBOutlet weak var errorLAbel: UILabel!
var userUid: String!
override func viewDidLoad() {
super.viewDidLoad()
SignupButton.layer.cornerRadius = 15
errorLAbel.alpha = 0
}
// Check fields, If everything is correct returns Nil otherwise returns error.
func validateFields() -> String? {
if Email.text?.trimmingCharacters(in: .whitespacesAndNewlines) == "" ||
Password.text?.trimmingCharacters(in: .whitespacesAndNewlines) == "" ||
Firstname.text?.trimmingCharacters(in: .whitespacesAndNewlines) == "" ||
Lastname.text?.trimmingCharacters(in: .whitespacesAndNewlines) == "" ||
City.text?.trimmingCharacters(in: .whitespacesAndNewlines) == "" ||
Street.text?.trimmingCharacters(in: .whitespacesAndNewlines) == "" ||
Gender.text?.trimmingCharacters(in: .whitespacesAndNewlines) == "" {
return "Please fill in all fields."
}
// Check if password is secure
let cleanedPassword = Password.text!.trimmingCharacters(in: .whitespacesAndNewlines)
if Utilities.isPasswordValid(cleanedPassword) == false {
// Password isn't secure enough
return "Please make sure your password is at least 8 characters, contains a special character and a number."
}
return nil
}
#IBAction func SignupTapped(_ sender: Any) {
//Validate
let error = validateFields()
if error != nil {
// Something is wrong with the fields
showError(error!)
}
else {
// Create User
// Create clean versions of data
let lastname = Lastname.text!.trimmingCharacters(in: .whitespacesAndNewlines)
let firstname = Firstname.text!.trimmingCharacters(in: .whitespacesAndNewlines)
let email = Email.text!.trimmingCharacters(in: .whitespacesAndNewlines)
let password = Password.text!.trimmingCharacters(in: .whitespacesAndNewlines)
let city = City.text!.trimmingCharacters(in: .whitespacesAndNewlines)
let street = Street.text!.trimmingCharacters(in: .whitespacesAndNewlines)
let gender = Gender.text!.trimmingCharacters(in: .whitespacesAndNewlines)
Auth.auth().createUser(withEmail: email, password: password) { (result, err) in
//check for errors
if err != nil {
// There was an error creating the user
self.showError("Error Creating User")
}
else {
//User was creating successfully now store
let db = Firestore.firestore()
db.collection("users").addDocument(data: ["firstname":firstname, "lastname":lastname, "City": city, "Street": street, "Gender":gender, "uid": result!.user.uid]) { (Error) in
if error != nil {
self.showError("Error saving user data")
}
}
// Move to homescreen
self.moveToHome()
}
}
}
}
func showError(_ message:String) {
errorLAbel.text = message
errorLAbel.alpha = 1
}
func moveToHome() {
let storyboard = UIStoryboard(name: "Main.storyboard", bundle: nil)
let homeViewController = storyboard?.instantiateViewController(identifier: "HomeVC") as? HomeViewController //This part gives error
view.window?.rootViewController = homeViewController
view.window?.makeKeyAndVisible()
}
}
(Ignore had to add extra text to be able to post)
try:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
uses "Main" instead of "Main.storyboard"
and make sure that the StoryboadID has been set
I'm using BEMCheckBox library for checkbox.
The thing is when checkbox is true it doesn't save the inputs from the users
What I tried to do is when checkbox == true
it should,
save email and password and and set checkbox to true, then save it to user default.
if == false
should delete everything (email, password and reset checkbox to false).
, but it's not working.
var Defaults = UserDefaults.standard
#IBOutlet weak var box1: BEMCheckBox!
struct keys {
static let emailKey = "emailTextField"
static let passwordKey = "passwordTextField"
static var boxBool = "boxBool"
}
override func viewDidLoad() {
didTap(box1)
box1.delegate = self
checkSavedData()
}
func didTap(_ checkBox: BEMCheckBox) {
if checkBox.on == true {
rememberMyEmailandPassword()
} else if checkBox.on == false {
Defaults.removeObject(forKey: keys.emailKey)
Defaults.removeObject(forKey: keys.passwordKey)
Defaults.removeObject(forKey: keys.boxBool)
}
}
func rememberMyEmailandPassword() {
Defaults.set(emailTextField.text, forKey: keys.emailKey)
Defaults.set(passwordTextField.text, forKey: keys.passwordKey)
Defaults.set(box1.on, forKey: keys.boxBool)
}
func checkSavedData() {
let email = Defaults.value(forKey: keys.emailKey) as? String ?? ""
let password = Defaults.value(forKey: keys.passwordKey) as? String ?? ""
let boxBoolean = Defaults.bool(forKey: keys.boxBool)
emailTextField.text = email
passwordTextField.text = password
box1.on = boxBoolean
}
I think the problem with boxBoolean. because I believe boxBoolean doesn't recall the data again.
Thnx.
var defaults = UserDefaults.standard
#IBOutlet weak var emailTextField: UITextField!
#IBOutlet weak var passwordTextField: UITextField!
#IBOutlet weak var box1: BEMCheckBox!
enum Keys: String {
case email, password, box1
}
override func viewDidLoad() {
// 1) loads the checkBox state when the view loads
box1.on = defaults.bool(forKey: Keys.box1.rawValue)
box1.delegate = self
// 2) update the UI in case it is checked
if box1.on {
loadData()
}
// 3) adds a control event for editing changed to both fields
emailTextField.addTarget(self, action: #selector(saveData), for: .editingChanged)
passwordTextField.addTarget(self, action: #selector(saveData), for: .editingChanged)
}
func didTap(_ checkBox: BEMCheckBox) {
// 4) saves the checkbox state
defaults.set(box1.on, forKey: Keys.box1.rawValue)
// 5) Saves field data or remove it
if box1.on {
defaults.set(emailTextField.text!, forKey: Keys.email.rawValue)
defaults.set(passwordTextField.text!, forKey: Keys.password.rawValue)
} else {
// 6) You should NEVER remove the checkbox value
defaults.removeObject(forKey: Keys.email.rawValue)
defaults.removeObject(forKey: Keys.password.rawValue)
}
}
#objc func saveData(_ textField: UITextField) {
// 7) update the data as the user types it in case it is checked
if box1.on {
defaults.set(emailTextField.text!, forKey: Keys.email.rawValue)
defaults.set(passwordTextField.text!, forKey: Keys.password.rawValue)
}
}
func loadData() {
// 8) updates the UI with the persisted data
// Note that text property is optional so you can pass an optional string (no need to unwrap it)
emailTextField.text = defaults.string(forKey: Keys.email.rawValue)
passwordTextField.text = defaults.string(forKey: Keys.password.rawValue)
}