How to create a new user in firebase - ios

I have been trying to follow the docs to authenticate a new user into firebase but when my user sign up their information is not appearing in firebase authentication
So I tried turning my password/email text field into a string that might help get rid of this issue but I received this error
Cannot convert value of type 'UITextField?' to expected argument type 'String'
so I tried using
let{
But now I can't type into the text field at all to enter the user data into firebase so how do I properly set up this code to authenticate my new user data ?
import UIKit
import FirebaseAuth
class SignUpViewController: UIViewController {
#IBOutlet weak var Email: UITextField!
#IBOutlet weak var Password: UITextField!
#IBOutlet weak var Username: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
let password = Password.text
let email = Email.text
Auth.auth().createUser(withEmail: email!, password: password!) { authResult, error in
if let error = error {
print("Error \(error.localizedDescription)")
return
} else {
}

Try using a different name for the variables, possibly lowercased instead of
let Password = Password.text
let Email = Email.text
use
let password = Password.text
let email = Email.text
in case the compiler is complaining and using the TextField instead of the text contained in it, or if you are using SwiftUI just pass a binging like so:
#State private var email: String = ""
#State private var password: String = ""
TextField("Email here...", text: $email)
SecureField("Password here...", text: $password)
Button {
// ... check if fields are not null
Auth.auth().createUser(withEmail: email, password: password) { res, err in
// ...
}
} label: {
Text("Create User")
}
EDIT 1:
Try this and make sure to create the right segues with right names if you are copy pasting and also that the storyboard components are correctly configured and allow write text.
#IBOutlet weak var emailTextField: UITextField!
#IBOutlet weak var passwordTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func createUser(_ sender: UIButton) {
if let email = emailTextField.text, let password =
passwordTextField.text {
// create the user with email and password
}
}

Related

How to add data to a specific uid in Firestore Database?

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
}
}

'AuthDataResult' has no member 'profileChangeRequest' [duplicate]

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
})
})

Query Data from Firebase and write in UITextfield

I'm trying to pull data from my firebase project and write the field value in a UITextfield. I can't seem to figure out how to query the data needed for the UITextfields from the firebase field values correctly.
Is there anyway to do this? I have only seen videos of people adding firebase documents to a tableview, not any for direct pull of a firebase value to a UITextfield.
I've tried:
Switching the constants to instance the UITextfield Outlets and optionally unwrap as text fields let username = data[USERNAME] as? UITextField ?? "anonymous"
Creating variables of the UITextfields and equal the collections array data. So something kind like... let self.username = Userdata[0] but I keep getting "expected pattern error"
I know these may not be appropriate syntax but this is the first time I've ever coded and attempted to make an app, but I can't find any tutorial to follow for this scenario. So any information greatly appreciated, Thanks.
Heres what I've got so far...
import UIKit
import FirebaseDatabase
import Firebase
class ProfileVC: UIViewController {
#IBOutlet weak var userImage: UIImageView!
#IBOutlet weak var username: UITextField!
#IBOutlet weak var firstname: UITextField!
#IBOutlet weak var userEmail: UITextField!
#IBOutlet weak var lastname: UITextField!
#IBOutlet private weak var bgView: UIView!
//variables
private var Userdatas = [Userdata]()
private var usersCollectionRef: CollectionReference!
override func viewDidLoad() {
super.viewDidLoad()
usersCollectionRef = Firestore.firestore().collection(USERS_REF)
}
override func viewWillAppear(_ animated: Bool){
usersCollectionRef.getDocuments { (snapshot, error) in
if let err = error {
debugPrint("Error fetching docs: \(err) ")
} else {
guard let snap = snapshot else{return}
for document in snap.documents {
let data = document.data()
let username = data[USERNAME] as? String ?? "anonymous"
let firstname = data[FIRST_NAME] as? String ?? "Anonymous"
let lastname = data[LAST_NAME] as? String ?? "Anonymous"
let email = data[EMAIL] as? String ?? "Anonymous"
let documentID = document.documentID
let newuserData = Userdata(username: username, email: email, firstname: firstname, lastname: lastname, documentID: documentID)
}
}
}
}

Use of undeclared type 'HomeViewController'

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

Firebase-Swift: How to add every created user to a friends list when created?

I am trying to create a social media app and in doing so I am trying to create a friends list in my database. I have the general idea of how the database is going to be structured but need help in the actual code of it as I am fairly new to Swift development.
This is my current database structure:
users
uid_0
name: "John"
email: "john#gmail.com"
uid_1
name: "Doe"
email: "doe#gmail.com"
uid_2
name: "User"
email: "user#gmail.com"
Here's my sign up view controller code
import Foundation
import Firebase
import SwiftKeychainWrapper
class SignUpVC: UIViewController {
#IBOutlet weak var emailField: UITextField!
#IBOutlet weak var usernameField: UITextField!
#IBOutlet weak var passField: UITextField!
#IBOutlet weak var cPassField: UITextField!
#IBOutlet weak var SignUpButton: UIButton!
var userUid: String!
var email: String!
var username: String!
var password: String!
var cPassword: String!
var friends: [String] = []
override func viewDidLoad() {
super.viewDidLoad()
self.view.addGestureRecognizer(UITapGestureRecognizer(target: self.view, action: #selector(UIView.endEditing(_:))))
// Do any additional setup after loading the view.
}
override func viewDidDisappear(_ animated: Bool) {
if let _ = KeychainWrapper.standard.string(forKey: "uid") {
performSegue(withIdentifier: "toLogin", sender: nil)
}
}
func printAlert(Header: String, Message: String) {
let alert = UIAlertController(title: Header, message: Message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: nil))
self.present(alert, animated: true)
}
#IBAction func createAccount (_ sender: AnyObject) {
if password != cPassword {
self.printAlert(Header: "Error", Message: "Passwords Do Not Match")
}
else{
guard let email = emailField.text, let password = passField.text, let username = usernameField.text else {
print("Form is not valid")
return
}
Auth.auth().createUser(withEmail: email, password: password, completion: { (res, error) in
if let error = error {
print(error)
if let error = AuthErrorCode(rawValue: error._code) {
switch error {
case .invalidEmail:
self.printAlert(Header: "Error", Message: "invalid email")
case .emailAlreadyInUse:
self.printAlert(Header: "Error", Message: "in use")
default:
self.printAlert(Header: "Error", Message: "Create User Error")
}
}
return
}
guard let uid = res?.user.uid else {
return
}
//successfully authenticated user
let ref = Database.database().reference(fromURL: "https://messagingdemo-af075.firebaseio.com/")
let usersReference = ref.child("users").child(uid)
let values = ["username": username, "email": email, "password": password]
usersReference.child("friends").setValue(self.friends)
usersReference.updateChildValues(values, withCompletionBlock: { (err, ref) in
if let err = err {
print(err)
return
}
self.performSegue(withIdentifier: "toHome", sender: nil)
})
})
}
}
}
I am trying to achieve a database structure that looks like this:
users
uid_1
name: "John"
email: "john#gmail.com"
friends
uid_2: = true
uid_3: = false
uid_2
name: "Doe"
email: "doe#gmail.com"
uid_3
name: "User"
email: "user#gmail.com"
I'm assuming that this is something where I'll have to add every created user id to every users friends list when a new user signs up. However, I don't get how to write that programmatically in swift and would appreciate some help.
You should use a model class that represent the User by taking the piece of code you wrote in your View Controller.
For example (check the Swift Structures and Classes documentation) :
class User {
var uID: String!
var email: String!
var name: String!
var password: String!
var friends: [String] = []
}
Then initialize a list of User in your View Controller.
var users: [User]
So the User model (in your database) looks pretty much the same except for the property friends. Since it is of type [String] (list of string), it should look like this:
We assume that John has for friend "user2", "user4" and "user9".
uID : "uID_1"
email : "john#mail.com"
name : "John"
password : "..."
friends : ["uID_2", "uID_4", "uID_9"]
I won't go in the details but:
You could also do it another way, separate the friends list from the user.
"uID_1" : ["uID_2", "uID_4", "uID_9"]
"uID_2" : ["uID_1", "uID_6"]
...
... Just to say that there is many ways to do it...

Resources