When I try to register a new user, I get an error saying value of type 'FIRDatabaseReference' has no member 'createuser'. See image below.
FIRAuth.auth()?.createUserWithEmail(<email: String>, password: <String>, completion: <FIRAuthResultCallback?(FIRUser?, NSError?) -> Void#>)
Here is a screenshot of how the code looks like picture of the code and the imageview:
Try this code it is working absolutely fine for me
//
// ViewController.swift
// FirebaseExample
//
// Created by Belal Khan on 03/10/16.
// Copyright © 2016 Belal Khan. All rights reserved.
//
import UIKit
//importing firebase
import Firebase
class ViewController: UIViewController {
//Textfields for email and password
#IBOutlet weak var textFieldEmail: UITextField!
#IBOutlet weak var textFieldPassword: UITextField!
//label for displaying message
#IBOutlet weak var labelMessage: UILabel!
//button for registration
#IBAction func buttonRegister(sender: UIButton) {
//do the registration operation here
//first take the email and password from the views
let email = textFieldEmail.text
let password = textFieldPassword.text
FIRAuth.auth()?.createUserWithEmail(email!, password: password!, completion: { (user: FIRUser?, error) in
if error == nil {
self.labelMessage.text = "You are successfully registered"
}else{
self.labelMessage.text = "Registration Failed.. Please Try Again"
}
})
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
//initialising firebase
FIRApp.configure()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Source: swift firebase tutorial
The code does not match. ref.createUser is different from FIRAuth.auth()?.createUserWithEmail
This is a working piece of code I tried a few days ago in XCode 7.3.1 I am not sure which version of XCode you are using. However, there's no pre-defined function as you tried!
func buttonHandleRegister() {
guard let email = emailTextField.text, password = passwordTextField.text, name = nameTextField.text else {
print("Form is not valid")
return
}
FIRAuth.auth()?.createUserWithEmail(email, password: password, completion: { (user: FIRUser?, error) in
if error != nil {
print("Error")
return
}
guard let uid = user?.uid else {
return
}
//successfully logged in
let ref = FIRDatabase.database().referenceFromURL("https://some-random-name.firebaseio.com/")
let usersReference = ref.child("users").child(uid)
let values = ["name" : name, "email": email, "password": password]
usersReference.updateChildValues(values, withCompletionBlock: { (err, ref)
in
if err != nil {
print(err)
return
}
print("Saved user succesfully")
})
})
}
Related
I'm following along in a tutorial on youtube about how to create the user login and registration. I've created three view controllers... SignInVC, SignOutVC, and SignUpVC.
The sign up functionality works perfectly within the simulator...however, when I try to do the sign in portion, it does not work at all. It does not throw any type of error...I just click the sign in button and nothing.
Note: I didn't see the connection in the connections inspector like I did with the sign up view...so I tried dragging the outlet over again (control and drag button to the SignInVC) and now I see the connection in the connection inspector but I get this error now.....
Reading from private effective user settings.
fatal error: unexpectedly found nil while unwrapping an Optional value
2017-09-04 14:50:03.988918-0400 Sample Project[12480:1387954] fatal error: unexpectedly found nil while unwrapping an Optional value
(lldb)
Here is my code for the sign in vc:
import UIKit
import Firebase
class SignInVC: UIViewController {
//outlets
#IBOutlet weak var emailTF: UITextField!
#IBOutlet weak var passwordTF: UITextField!
//action
#IBAction func onSignInTapped(_ sender: Any) {
guard let email = emailTF.text,
email != "",
let password = passwordTF.text,
password != ""
else {
AlertController.showAlert(self, title: "Missing Info", message: "Please fill out all required fields")
return
}
Auth.auth().signIn(withEmail: email, password: password, completion: { (user, error) in
guard error == nil else{
AlertController.showAlert(self, title: "Error", message: error!.localizedDescription)
return
}
guard let user = user else { return }
print(user.email ?? "MISSING EMAIL")
print(user.displayName ?? "MISSING DISPLAY NAME")
print(user.uid)
self.performSegue(withIdentifier: "signInSegue", sender: nil)
})
}
}
As mentioned earlier, my signup works perfectly. here is the code for that...if it helps..
import UIKit
import Firebase
class SignUpVC: UIViewController {
//outlets
#IBOutlet weak var usernameTF: UITextField!
#IBOutlet weak var emailTF: UITextField!
#IBOutlet weak var passwordTF: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
//actions
#IBAction func onSignUpTapped(_ sender: Any) {
guard let username = usernameTF.text,
username != "",
let email = emailTF.text,
email != "",
let password = passwordTF.text,
password != ""
else {
AlertController.showAlert(self, title: "Missing Info", message: "Please fill out all fields")
return
}
Auth.auth().createUser(withEmail: email, password: password, completion: { (user, error) in
guard error == nil else {
AlertController.showAlert(self, title: "Error", message: error!.localizedDescription)
return
}
guard let user = user else { return }
print(user.email ?? "Missing Email")
print(user.uid)
let changeRequest = user.createProfileChangeRequest()
changeRequest.displayName = username
changeRequest.commitChanges(completion: { (error) in
guard error == nil else {
AlertController.showAlert(self, title: "Error", message: error!.localizedDescription)
return
}
self.performSegue(withIdentifier: "signUpSegue", sender: nil)
})
})
}
}
Try in capacitor.config set server: { iosScheme: "ionic" }
I can't transfer the login manager result between view controllers,
The segue is associated to the button and its identifier is s1.
My setup is correct.The program is crashing with green breakpoints.
here is my code:
for the first VC:
import FBSDKLoginKit
class ViewController: UIViewController {
var user_name: String?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let fbLoginManager = FBSDKLoginManager()
fbLoginManager.logIn(withReadPermissions: ["public_profile", "email"], from: self) { (result, error) in
if let error = error {
print("Failed to login: \(error.localizedDescription)")
return
}
guard let accessToken = FBSDKAccessToken.current() else {
print("Failed to get access token")
return
}
let credential = FIRFacebookAuthProvider.credential(withAccessToken: accessToken.tokenString)
FBSDKGraphRequest(graphPath: "/me", parameters: ["fields" : "email, id, locale"])
.start(completionHandler: { (connection, result, error) in
guard let result = result as? NSDictionary,
let user_name = result["user_name"] as? String,
else {
return
}
if(segue.identifier == "s1"){
if let v = segue.destination as? Re {
v.uname=user_name ?? ""
//v.uname = usr.text ?? ""
}
}
})
// Perform login by calling Firebase APIs
FIRAuth.auth()?.signIn(with: credential, completion: { (user, error) in
if let error = error {
print("Login error: \(error.localizedDescription)")
let alertController = UIAlertController(title: "Login Error", message: error.localizedDescription, preferredStyle: .alert)
return
}
})
}
}
}
And for Re,the next VC:
class Re: UIViewController {
var uname: String?
#IBOutlet weak var l1: UILabel!
var userfb: String?
override func viewDidLoad() {
super.viewDidLoad()
l1.text=uname
// Do any additional setup after loading the view.
}
}
You need to use instance variable which you have declared at top as below.
Now you have create new user_name and use another user_name
guard let result = result as? NSDictionary,
user_name = result["user_name"] as? String,// make change here
else {
return
}
Problem: For some reason the data is not being sent to my database in firebase. Can anyone figure out why the information is not being sent?
I highlighted the code with //******** to show where I am sending it.
Rules:
{
"rules": {
".read": "true",
".write": "true"
}
}
import UIKit
import Firebase
import FirebaseDatabase
import KeychainSwift
class SignUpController: UIViewController {
//INPUT - from keyboard email & password
#IBOutlet weak var emailField: UITextField!
#IBOutlet weak var passwordField: UITextField!
//Data Base Initialization
//var ref: FIRDatabaseReference!
let dataRef = FIRDatabase.database().reference()
override func viewDidLoad() {
super.viewDidLoad()
}
//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)
}
}
func CompleteSignIn(id: String){
let keyChain = DataService().keyChain
keyChain.set(id , forKey: "uid")
}
//If SignUp button is pressed user will be directed to sign up page
#IBAction func LoginPressed(_ sender: Any) {
self.performSegue(withIdentifier: "BackToLogin", sender: nil)
}
/*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.CompleteSignIn(id: user!.uid) //Completese Database Sign in
//************************************************
//Send information to Database
let userEmail : String = self.emailField.text!
let userPassword : String = self.passwordField.text!
let userID : String = user!.uid
self.dataRef.child("Users").child(userID).setValue(["Email": userEmail, "Password" : userPassword])
//************************************************
print("Sign in Test")
self.performSegue(withIdentifier: "SignIn", sender: nil)
} else {
FIRAuth.auth()?.createUser(withEmail: email, password: password) { (user, error) in
if error != nil {
Alerts().invalidSignUpAlert(sender: self) //Alert for invalid email & Password
print("cant sign in user") //Programmer Debugging
} else {
self.CompleteSignIn(id: user!.uid)
self.performSegue(withIdentifier: "SignIn", sender: nil)
}
}
}
}
}
}
}
Add "Users" in the rules as shown below:
"rules": {
"Users":{
".read": "true",
".write": "true"
}
}
You need as Boolean, not as string "true"
{
"rules": {
".read" : true,
".write":true
}
}
Firebase Authentication - Can't retrieve user data after login.
I'm trying to retrieve the users email after sign in (logincontroller) and display it in a UILABEL on another controller (maincontroller). When you create a user or use an existing one, it works fine the first time after launching the app, but when you sign out and try to use another email it does not work.
I have two view controllers:
import UIKit
import Firebase
import FirebaseAuth
import FirebaseDatabase
class LoginViewController: UIViewController {
var ref: FIRDatabaseReference!
#IBOutlet weak var emailTextField: UITextField!
#IBOutlet weak var passwordTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
ref = FIRDatabase.database().reference()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func signInButton(sender: AnyObject) {
FIRAuth.auth()?.signInWithEmail(emailTextField.text! , password: passwordTextField.text!, completion: { (user, error) in
if error != nil {
print(error!.localizedDescription)
}
})
self.performSegueWithIdentifier("MainViewSegue", sender: self)
}
#IBAction func createAccountButton(sender: AnyObject) {
FIRAuth.auth()?.createUserWithEmail(emailTextField.text!, password: passwordTextField.text!, completion: { (user, error) in
if error != nil {
print(error!.localizedDescription)
} else {
print("User Created.")
let userID: String = user!.uid
let userEmail:String = self.emailTextField.text!
self.ref.child("users").child(userID).setValue(["email": userEmail])
}
})
}
}
and:
import Foundation
import UIKit
import Firebase
import FirebaseDatabase
class MainViewController: UIViewController {
var ref: FIRDatabaseReference!
var refHandle: UInt!
#IBOutlet weak var userEmailLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
ref = FIRDatabase.database().reference()
refHandle = ref.observeEventType(FIRDataEventType.Value, withBlock: { (snapshot) in
let dataDict = snapshot.value as! [String: AnyObject]
print((dataDict))
})
let userID: String = (FIRAuth.auth()?.currentUser?.uid)!
ref.child("users").child(userID).observeSingleEventOfType(.Value, withBlock: { (snapshot) in
let userEmail = snapshot.value!["email"] as! String
self.userEmailLabel.text = userEmail
})
}
#IBAction func signOutButton(sender: AnyObject) {
try! FIRAuth.auth()!.signOut()
if let storyboard = self.storyboard {
let viewController = storyboard.instantiateViewControllerWithIdentifier("LoginViewController")
self.presentViewController(viewController, animated: false, completion: nil)
}
}
}
This is where I get the error EXC_BAD_INSTRUCTION:
let userID: String = (FIRAuth.auth()?.currentUser?.uid)!
CMD+CLICK on signInWithEmail in FIRAuth.auth()?.signInWithEmail(emailT... and you will be directed to its documentation, above that function in its documentation you will see :-
#param completion Optionally; a block which is invoked when the sign in flow finishes, or is
canceled. Invoked asynchronously on the main thread in the future.
which means your completionBlock is invoked when your user is either signed in or signInWithEmail function has given some error.But in your case self.performSegueWithIdentifier("MainViewSegue", sender: self) will get called even before your completionBlock: is called.
Try this:-
#IBAction func signInButton(sender: AnyObject) {
FIRAuth.auth()?.signInWithEmail(emailTextField.text! , password: passwordTextField.text!, completion: { (user, error) in
if error != nil {
print(error!.localizedDescription)
}else if error == nil{
self.performSegueWithIdentifier("MainViewSegue", sender: self)
}
})
}
Also replace :-
let userID: String = (FIRAuth.auth()?.currentUser?.uid)!
with
let userID: String = FIRAuth.auth()!.currentUser!.uid
No need to forcefully unwrap an optional value which you know does exist
Is there a better way to make a user automatically login to the app as long as they have logged in in the past; other than saving their login details directly to the storage which may be insecure?
Thanks
PS: I'm using Firebase and Swift for iOS
EDIT: Here's the code
import UIKit
import Firebase
class loginVC: UIViewController {
#IBOutlet weak var emailTextField: UITextField!
#IBOutlet weak var passwordTextField: UITextField!
#IBOutlet weak var errorLabel: UILabel!
override func viewDidAppear(animated: Bool) {
automaticLogin()
}
#IBAction func loginTapped(sender: AnyObject) {
errorLabel.text = ""
FIRAuth.auth()?.createUserWithEmail(emailTextField.text!, password: passwordTextField.text!, completion: {
user, error in
if error != nil {
FIRAuth.auth()?.signInWithEmail(self.emailTextField.text!, password: self.passwordTextField.text!, completion: { (user, error) in
if error == nil {
self.login()
} else if error != nil {
self.errorLabel.text = ("Invalid email address or password")
print(error)
}
})
} else {
print("user created")
self.login()
print(user?.displayName)
}
})
}
#IBAction func forgotPasswordTapped(sender: AnyObject) {
let email = emailTextField.text
errorLabel.text = ""
FIRAuth.auth()?.sendPasswordResetWithEmail(email!) { error in
if error != nil {
self.errorLabel.text = ("Invalid email address")
print(error)
} else {
self.errorLabel.text = ("Password reset email successfully sent")
print("password reset email sent")
}
}
}
func login() {
FIRAuth.auth()?.signInWithEmail(emailTextField.text!, password: passwordTextField.text!, completion: {
user, error in
if error != nil {
self.errorLabel.text = ("Invalid email address or password")
print(error)
} else {
print("login successful")
self.checkIfUserIsNew()
}
})
}
func checkIfUserIsNew() {
if FIRAuth.auth()?.currentUser?.displayName != nil || FIRAuth.auth()?.currentUser?.displayName == "" {
self.performSegueWithIdentifier("showChatVC", sender: self)
} else {
self.performSegueWithIdentifier("showOptionsVC", sender: self)
}
}
func automaticLogin() {
FIRAuth.auth()?.addAuthStateDidChangeListener { auth, user in
if user == user {
print("still signed in")
} else {
print("not signed in")
}
}
}
I also used this to logout the user:
#IBAction func logOutTapped(sender: AnyObject) {
try! FIRAuth.auth()?.signOut()
performSegueWithIdentifier("showLoginVC", sender: self)
print(FIRAuth.auth()?.currentUser?.displayName)
}
You might want to use NSUserDefaults. To do this in your login() function you might want to save your user's data once they signed in or create an account. Inside your login function you can start by creating new variable to grab your user's email / password.
let userDefaults = UserDefaults.standard
userDefaults.setValue(self.emailField.text!, forKey: "email")
userDefaults.setValue(self.passField.text!, forKey: "password")
Next, you also need to implement a new function called viewWillAppear, which will be called before the view controller. And you might also put some arguments inside your login function.
override func viewWillAppear(_ animated: Bool) {
let userDefaults = UserDefaults.standard
if userDefaults.string(forKey: "email") != nil {
let email = userDefaults.string(forKey: "email")
let password = userDefaults.string(forKey: "password")
login(email: email!, password: password!)
}
}
the if statement will check wether your user already registered their email account or not yet. Lastly you need to update your login function to have two parameters, to pass in the email and password of the user.