i have watched some tutorial about save user info to DataBase after register or SignUp in the app but the problem that he save all the users by there uid and what i want is to save the users by there usernames what do you think is the professional or the better way to do that or it doesn't matter to chat app
#IBAction func SignUp(_ sender: Any) {
if username.text != nil, email.text != nil, password.text != nil, fullname.text != nil {
activityIndicator.startAnimating()
Auth.auth().createUser(withEmail: email.text!, password: password.text!, completion: { (user, error) in
if error != nil {
AlertController.showAlert(self, titel: "Error", message:".Fill all fields\n .User do exists\n .Network error ")
self.activityIndicator.stopAnimating()
return
}
let uid = user?.uid
let storageRef = Storage.storage().reference(forURL: "gs://,,,,,,,,,.com").child("profile_image").child(uid!)
if let profileImg = self.selectedImage, let imageData = UIImageJPEGRepresentation(profileImg, 0.1){
storageRef.putData( imageData, metadata: nil, completion: { (metadata, error) in
if error != nil{
return
}
let profileImageUrl = metadata?.downloadURL()?.absoluteString
let ref = Database.database().reference()
let usersReferance = ref.child("users")
let newUserReferance = usersReferance.child(uid!)
newUserReferance.setValue(["fullname": self.fullname.text, "username": self.username.text, "email": self.email.text, "password": self.password.text, "profileImageUrl": profileImageUrl])
})
}
self.dismiss(animated: true, completion: nil)
self.activityIndicator.stopAnimating()
})
}
}
}
if you want to save the users by their username yes you can do as follow
#IBAction func SignUp(_ sender: Any) {
if username.text != "", email.text != "", password.text != "", fullname.text != "" {
activityIndicator.startAnimating()
Auth.auth().createUser(withEmail: email.text!, password: password.text!, completion: { (user, error) in
if error != nil {
AlertController.showAlert(self, titel: "Error", message:".Fill all fields\n .User do exists\n .Network error ")
self.activityIndicator.stopAnimating()
return
}
let uid = user?.uid // here you are providing userID
let storageRef = Storage.storage().reference(forURL: "gs://.........com").child("profile_image").child(uid!)
if let profileImg = self.selectedImage, let imageData = UIImageJPEGRepresentation(profileImg, 0.1){
storageRef.putData( imageData, metadata: nil, completion: { (metadata, error) in
if error != nil{
return
}
let profileImageUrl = metadata?.downloadURL()?.absoluteString
let ref = Database.database().reference()
let usersReferance = ref.child("users")
// let newUserReferance = usersReferance.child(uid!) //here in ref you are creating a node with UID
//use your username
let newUserReferance = usersReferance.child(username.text!)
//set child values here as you doing
newUserReferance.setValue(["fullname": self.fullname.text, "username": self.username.text, "email": self.email.text, "password": self.password.text, "profileImageUrl": profileImageUrl])
})
}
self.dismiss(animated: true, completion: nil)
self.activityIndicator.stopAnimating()
})
}
}
For 2 . 1) I do not think it will be a bette approach as if you set node with username if while signUp other user filled same username data will be replaced with new data
2) if you use some checks that username is valid or not it will work , but just for concern need a additional reference in database for it to check username is available or not
-- Do as check in whole database that username is taken or not
-- or make a node with list of usernames and and get all those in array and check offline for a fast response with textfield validations or can even put observe event
Related
enter image description here
#error >> Type of expression is ambiguous without more context.
Auth.auth().createUser(withEmail: email, password: password) { AuthDataResult, error in
// handle error
if let error = error {
print("Failed to create a user with error", error.localizedDescription)
return
}
// set profile image
guard let profileImage = self.plusPhotoButton.imageView?.image else { return }
//upload data
guard let uploadData = profileImage.jpegData(compressionQuality: 0.3) else { return }
// place image in database
let filename = NSUUID().uuidString
let storageRef = Storage.storage().reference().child("profile_image").child(filename)
storageRef.putData(uploadData, metadata: nil, completion: {(metadata, error) in
// handle error
if let error = error {
print("Faild to upload image to firebase storage with error", error.localizedDescription)
}
// profile image URL
guard let profileImageURL = metadata?.downloadURL()?.absoluteString else { return }
//user Id
guard let uid = AuthDataResult?.user.uid else { return }
//guard let fcmToken = messaging.messagin().fcmToken else { return }
let dictionaryValues = ["name": fullName,
"username": username,
"profileImageURL": profileImageURL]
let values = [uid: dictionaryValues]
//save data info to database
Database.database().reference().child("users").updateChildValues(values, withCompletionBlock: { (error, ref) in
print("Successfully created user and saved indformation to database")
})
})
}
i import Firebase but still not working.
I'm implementing a sign in with Twitter option on my app (with TwitterKit) but it keeps crashing on the function below - saveUserIntoFirebaseDatabase (when uploading the user data, image to Firebase database). I can't understand how OR why the function below needs to be in the main queue?
The user data is fetched and saved to the Firebase Auth section however it seems to crash after that when trying to save the user data to the Realtime Database & Storage?
fileprivate func saveUserIntoFirebaseDatabase() {
guard let uid = Auth.auth().currentUser?.uid,
let name = self.name,
let username = self.username,
let email = self.email,
let profileImage = profileImage,
let profileImageUploadData = UIImageJPEGRepresentation(profileImage, 0.3) else { Service.dismissHud(self.hud, text: "Error", detailText: "Failed to save user.", delay: 3); return }
let filename = UUID().uuidString
let storageRef = Storage.storage().reference().child("profile_images").child(filename)
storageRef.putData(profileImageUploadData, metadata: nil, completion: { (metadata, err) in
if let err = err {
Service.dismissHud(self.hud, text: "Error", detailText: "Failed to save user with error: \(err)", delay: 3);
return
}
// Firebase 5 Update: Must now retrieve downloadURL
storageRef.downloadURL(completion: { (downloadURL, err) in
guard let profileImageUrl = downloadURL?.absoluteString else { return }
print("Successfully uploaded profile image into Firebase storage with URL:")
let dictionaryValues = ["name": name,
"email": email,
"username": username,
"profileImageUrl": profileImageUrl]
let values = [uid : dictionaryValues]
Database.database().reference().child("users").updateChildValues(values, withCompletionBlock: { (err, ref) in
if let err = err {
Service.dismissHud(self.hud, text: "Error", detailText: "Failed to save user info with error: \(err)", delay: 3)
return
}
print("Successfully saved user info into Firebase database")
// after successfull save dismiss the welcome view controller
self.hud.dismiss(animated: true)
self.dismiss(animated: true, completion: nil)
})
})
})
}
The MainTabBarController I have setup has the following to see if the current user is logged in, if not they get re-directed to the Welcome Controller. Could this be the cause?
fileprivate func checkLoggedInUserStatus() {
if Auth.auth().currentUser == nil {
DispatchQueue.main.async {
let welcomeController = WelcomeController()
let welcomeNavigationController = UINavigationController(rootViewController: welcomeController)
self.present(welcomeNavigationController, animated: false, completion: nil)
return
}
}
}
I think you're trying to dismiss the viewcontroller on a background thread.
when the user sign up firebase authenticate the user and Upload his values like username and email and Profile Image but if he skip the Profile Image the user Will pass the auth and his email registered but firebase will not set the username and email and dismiss the profile image
#IBAction func SignUp(_ sender: Any) {
if username.text != "", email.text != "", password.text != "", fullname.text != "" {
activityIndicator.startAnimating()
Auth.auth().createUser(withEmail: email.text!, password: password.text!, completion: { (user, error) in
if error != nil {
AlertController.showAlert(self, titel: "Error", message:".Fill all fields\n .User do exists\n .Network error ")
self.activityIndicator.stopAnimating()
return
}
let uid = user?.uid
let storageRef = Storage.storage().reference(forURL: "gs://........com").child("profile_image").child(uid!)
if let profileImg = self.selectedImage, let imageData = UIImageJPEGRepresentation(profileImg, 0.1){
storageRef.putData( imageData, metadata: nil, completion: { (metadata, error) in
if error != nil{
return
}
let profileImageUrl = metadata?.downloadURL()?.absoluteString
let ref = Database.database().reference()
let usersReferance = ref.child("users")
let newUserReferance = usersReferance.child(self.username.text!).child(uid!)
newUserReferance.setValue(["fullname": self.fullname.text, "username": self.username.text, "email": self.email.text, "password": self.password.text, "profileImageUrl": profileImageUrl])
})
}
self.dismiss(animated: true, completion: nil)
self.activityIndicator.stopAnimating()
})
}
}
}
You must set the values to the different fields outside the image checker closure or they won't set if selectedImage is nil.
#IBAction func SignUp(_ sender: Any) {
if username.text != "", email.text != "", password.text != "", fullname.text != "" {
activityIndicator.startAnimating()
Auth.auth().createUser(withEmail: email.text!, password: password.text!, completion: { (user, error) in
if error != nil {
AlertController.showAlert(self, titel: "Error", message:".Fill all fields\n .User do exists\n .Network error ")
self.activityIndicator.stopAnimating()
return
}
let uid = user?.uid
var userValues = [
"fullname": self.fullname.text,
"username": self.username.text,
"email": self.email.text,
"password": self.password.text
]
let storageRef = Storage.storage().reference(forURL: "gs://........com").child("profile_image").child(uid!)
if let profileImg = self.selectedImage, let imageData = UIImageJPEGRepresentation(profileImg, 0.1){
storageRef.putData( imageData, metadata: nil, completion: { (metadata, error) in
if error != nil{
return
}
let profileImageUrl = metadata?.downloadURL()?.absoluteString
userValues["profileImageUrl"] = profileImageUrl
setData(userValues, uid!)
})
} else {
setData(userValues, uid!)
}
self.dismiss(animated: true, completion: nil)
self.activityIndicator.stopAnimating()
})
}
}
func setData(_ data: [String: Any], uid: Int) {
let ref = Database.database().reference()
let usersReferance = ref.child("users")
let newUserReferance = usersReferance.child(data["username"]).child(uid)
newUserReferance.setValue(data)
}
You should use a function to store the data too because the putData of the image is asyncronous.
I am unable to understand what exactly the error is trying to tell me. I tried fixing it by using self and changing classes. Still will not help. Need a guide that could help understand what exactly I am missing or doing wrong.
import UIKit
import Foundation
import Firebase
extension LoginController: UIImagePickerControllerDelegate,UINavigationControllerDelegate{
func handleRegister(){
guard let email = emailTextField.text, let password = passwordTextField.text, let name = nameTextField.text
else {
print("This form is not valid")
return
}
Auth.auth().createUser(withEmail: email, password: password) { (self, error) in
if error != nil {
print(error!)
return
}
guard let uid = self?.uid else{
return
}
//sucessfully authenticated user
let storageRef = Storage.storage().reference()
// On the following line
if let uploadData = UIImagePNGRepresentation(self.profileImageView.image!) {
storageRef.putData(uploadData, metadata: nil, completion: { (metadata, error) in
if error != nil{
print(error)
return
}
})
}
let ref = Database.database().reference(fromURL: "https://bbooks-96cac.firebaseio.com/")
let userReference = ref.child("user").child(uid)
let values = ["name": name, "email": email]
userReference.updateChildValues(values, withCompletionBlock: {
(err, ref) in
if err != nil {
print(err)
return
}
// print("Saved user successfully into firebase DB")
})
}
dismiss(animated: true, completion: nil)
}
}
First, you are misusing the term self (I'm surprised there is no error here). You need a better variable name:
Auth.auth().createUser(withEmail: email, password: password) { (self, error) in
I would change self to user here and throughout what follows:
Auth.auth().createUser(withEmail: email, password: password) { (user, error) in
Second, user is then an Optional so you need to unwrap it:
if let uploadData = UIImagePNGRepresentation(user!.profileImageView.image!) {
I am trying to setup a method to allow users to login to their Firebase accounts using Facebook. If it is a first time user creating an account everything works fine, but if a user made an account before and is trying to login in to their account is where the trouble begins. When the code
FIRAuth.auth()?.signIn(with: credential, completion: {(user, error)
runs I get the error saying that the email is already in use, even though it is the account in which they are trying to sign in for.
My entire code is here:
func handleCustomFBLogin() {
FBSDKLoginManager().logIn(withReadPermissions: ["email"], from: self) { (result, err) in
if err != nil {
print("Error loggin in is \(err)")
//self.facebookanimateIn()
} else if (result?.isCancelled)!{
print("The user cancelled loggin in ")
} else {
let credential = FIRFacebookAuthProvider.credential(withAccessToken: FBSDKAccessToken.current().tokenString)
let graphRequest : FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me", parameters: ["fields": "id, name, email"])
graphRequest.start(completionHandler: { (connection, result, error) -> Void in
if ((error) != nil) {
print("Error: \(error)")
} else {
let data:[String:AnyObject] = result as! [String: AnyObject]
let facebookName:NSString = data["name"] as! NSString
let facebookEmail = data["email"] as Any
let userId = data["id"] as! NSString
let facebookProfileUrl = "http://graph.facebook.com/\(userId)/picture?type=large"
let facebookAge = data["age_range"] as Any
let password = "needToPutRandomizedPasswordInHere" as String
FIRAuth.auth()?.createUser(withEmail: facebookEmail as! String, password: password, completion: {result, error in
if error != nil{
//user has account, they just need to sign in
FIRAuth.auth()?.signIn(with: credential, completion: {(user, error) in
if error != nil{
print(error.debugDescription)
return
}
let storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let vc: UINavigationController = storyboard.instantiateViewController(withIdentifier: "checker") as! UINavigationController
self.present(vc, animated: true, completion: nil)
// ref.removeObserver(withHandle: handle)
})
} else {
//user does not have an account and they need to create one
guard let uid = result?.uid else{
return
}
print("user created as \(uid)")
let val = "0"
let number = (val as NSString).integerValue
let ref = FIRDatabase.database().reference()
let usersReference = ref.child("Users").child(uid)
let values = [""] as [String : Any];
usersReference.updateChildValues(values, withCompletionBlock: { (err,ref) in
if err != nil {
print(err.debugDescription)
return}})
print("Save the user successfully into Firebase database")
let storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let vc: UINavigationController = storyboard.instantiateViewController(withIdentifier: "checker") as! UINavigationController
self.present(vc, animated: true, completion: nil)
}
})
}
})
}
}
}
once you have created the user, all you need is the login step
FIRAuth.auth()?.signIn(withEmail: email, password: password, completion: { (user, error) in
if error != nil {
// handle errors
} else {
// continue with login process
}
})