Value of type 'AuthDataResult' has no member 'uid' problem - ios

I am a newbie in Swift, learning from building a social media app following a tutorial of Kasey Schlaudt on youtube. When I write this line KeychainWrapper.standard.set((user?.uid)!, forKey: "KEY_UID") at minutes 36:11 if this video: https://youtu.be/gBB5tnAzjjo?t=2171 I get this error —> Value of type 'AuthDataResult' has no member 'uid'. Any suggestions on why this might be happening?
This is my code so far:
import UIKit
import Firebase
import SwiftKeychainWrapper
class ViewController: UIViewController {
#IBOutlet weak var UserImageView: UIButton!
#IBOutlet weak var usernameField: UITextField!
#IBOutlet weak var emailField: UITextField!
#IBOutlet weak var passwordField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func signInPress(_ sender: Any) {
if let email = emailField.text, let password = passwordField.text {
Auth.auth().createUser(withEmail: email, password: password) { (user, error) in
if error != nil {
//Create account
} else {
KeychainWrapper.standard.set((user?.uid)!, forKey: "KEY_UID")
}
}
}
}
}
Any help would be much appreciated !

The API documentation for createUser says that it provides an AuthDataResult object as the result. As you can see from link, it doesn't have a uid property. You will want to use its user property to get a User object that does have a uid.
Auth.auth().createUser(withEmail: email, password: password) { (result, error) in
if error != nil {
//Create account
} else {
KeychainWrapper.standard.set((result?.user.uid)!, forKey: "KEY_UID")
}
}

Related

How to add a user with setValue from Firebase Reading and writing data in ios

I am a newbie in Swift and I am learning by building a social media application.
I am struck at trying to implement self.ref.child("users").child(user.uid).setValue(["username": username]) in my code (from https://firebase.google.com/docs/database/ios/read-and-write).
I have been following the instructions of Kasey Schlaudt and at this point of the tutorial https://youtu.be/GrRggN41VF0?t=619 he tried to add a user with setValue as shown in the Firebase documentation I have linked. The errors I get in the line self.ref.child("users").child(user.uid).setValue(["username": username]) are
Use of unresolved identifier 'user' and Use of unresolved identifier 'username'.
My code so far (with some little changes from the original code in the video in my signInPress function) is
import UIKit
import Firebase
import SwiftKeychainWrapper
class ViewController: UIViewController {
#IBOutlet weak var UserImageView: UIButton!
#IBOutlet weak var usernameField: UITextField!
#IBOutlet weak var emailField: UITextField!
#IBOutlet weak var passwordField: UITextField!
override func viewDidLoad()
{
super.viewDidLoad()
}
override func viewDidAppear(_ animated: Bool)
{
if let _ : Bool = KeychainWrapper.standard.string(forKey: "uid") != nil
{
self.performSegue(withIdentifier: "toFeed", sender: nil)
}
}
func storeUserData(userID: String)
{
//---------------------------problematic line---------------------------
//from https://firebase.google.com/docs/database/ios/read-and-write
//from https://youtu.be/GrRggN41VF0?t=619
self.ref.child("users").child(user.uid).setValue(["username": username])
([
"username": usernameField.text
])
}
#IBAction func signInPress(_ sender: Any)
{
//this way you make sure there is a property inside emailField.text and you have a variable you can easily use
if let email = emailField.text, let password = passwordField.text
{
Auth.auth().signIn(withEmail: email, password: password)
{ (result, error) in
if error != nil && self.usernameField.text!.isEmpty && self.UserImageView.image != nil
{
Auth.auth().createUser(withEmail: email, password: password)
{ (result, error) in
self.storeUserData(userID: (result?.user.uid)!)
KeychainWrapper.standard.set((result?.user.uid)!, forKey: "KEY_UID")
self.performSegue(withIdentifier: "toFeed", sender: nil)
}
} else
{
KeychainWrapper.standard.set((result?.user.uid)!, forKey: "KEY_UID")
self.performSegue(withIdentifier: "toFeed", sender: nil)
}
}
}
}
}
I would very much appreciate any indication as to why the error does not occur for Kasey and what I might need to change to do the same process.
Thank you in advance !
You're actually pretty close, more of a typo issue. See that your storeUserData function is expecting a string called userID? That's what's needed in the line to store that data instead of user.uid
func storeUserData(userID: String) {
let username = self.usernameField.text
self.ref.child("users").child(userID).setValue(["username": username])
here ^^^^^^ userID instead of user.uid
}

Swift Firebase says internal error when creating a new user

I am trying to create new users with Firebase but it is giving me the message "An internal error has occurred, print and inspect the error details for more information." I have enabled the email password authentication on Firebase as well.
This is all the code that I have written as a test and it still doesn't work.
import UIKit
import Firebase
class ViewController: UIViewController {
#IBOutlet weak var emailTextField: UITextField!
#IBOutlet weak var pwordTxtField: UITextField!
#IBOutlet weak var continuebutton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func button(_ sender: Any) {
let email = emailTextField.text
let password = pwordTextField.text
Auth.auth().createUser(withEmail: email! , password: password!, completion: { (user, error) in
if let error = error {
print(error.localizedDescription)
}
else {
print("Success")
}
})
}
}
What I am doing wrong.
Thanks!
Include the following pods in your Podfile:
pod 'Firebase/Auth'
open the auth section and enable Email/password sign-in method and save.
make sure you have added GoogleService-Info.plist file in your project.
in Appdelegate :-
import Firebase
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions:
[UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
FirebaseApp.configure()
return true
}
In Viewcontroller:-
import UIKit
import Firebase
class ViewController: UIViewController {
#IBOutlet weak var emailTextField: UITextField!
#IBOutlet weak var pwordTxtField: UITextField!
#IBOutlet weak var continuebutton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func button(_ sender: Any) {
let email = emailTextField.text
let password = pwordTextField.text
Auth.auth().createUser(withEmail: email! , password: password!,
completion: { (user, error) in
if let error = error {
print(error.localizedDescription)
}
else {
print("Success")
}
})
}
}

How to send Facebook values to next screen in Xcode 8, swift 3

I'm putting together a series of registration pages where users are first presented with a "create account using Facebook" button, which logs them in, and then presents them with a basic registration page filled with empty text boxes. However, I am trying to populate some of these text boxes with the users' values gathered from the Graph Request.
Here is the first screen with the registration button:
import UIKit
import FBSDKLoginKit
class RegisterVC: UIViewController, FBSDKLoginButtonDelegate {
var fbLoginSuccess = false
var fbName:String!
var fbEmail:String!
override func viewDidLoad() {
super.viewDidLoad()
let loginButton = FBSDKLoginButton()
view.addSubview(loginButton)
loginButton.frame = CGRect(x: 82, y: 325, width: view.frame.width - 210, height: 59)
loginButton.delegate = self
}
func loginButtonDidLogOut(_ loginButton: FBSDKLoginButton!) {
print("Did log out of facebook")
}
func loginButton(_ loginButton: FBSDKLoginButton!, didCompleteWith result: FBSDKLoginManagerLoginResult!, error: Error!) {
if error != nil {
print(error)
return
}
print("Successfully logged in")
FBSDKGraphRequest(graphPath: "/me", parameters: ["fields": "id, name, email"]).start {(connection, result, err) in
if err != nil {
print("Failed to start graph request", err)
return
} else {
guard let data = result as? [String:Any] else {return}
let fbEmail = data["email"]
let fbName = data["name"]
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let vc = segue.destination as? CreateAccountVC
vc!.email.text = self.fbEmail
vc!.fullname.text = self.fbName
}
}
print(result)
}
performSegue(withIdentifier: "regSegue", sender: RegisterVC.self)
}
And these are the text boxes on the next screen:
import UIKit
class CreateAccountVC: UIViewController {
#IBOutlet weak var fullname: UITextField!
#IBOutlet weak var username: UITextField!
#IBOutlet weak var age: UITextField!
#IBOutlet weak var email: UITextField!
#IBOutlet weak var verifyEmail: UITextField!
#IBOutlet weak var password: UITextField!
#IBOutlet weak var verifyPassword: UITextField!
All the code above presents me with the registration page, but the text boxes are empty and not populated with the Facebook data. I'm not a great coder and really and help would be useful. Let me know if you have any solutions! Thanks.
The problem exists in this snippet:
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let vc = segue.destination as? CreateAccountVC
vc!.email.text = self.fbEmail
vc!.fullname.text = self.fbName
CreateAccountVCs textfields have not been created at the moment when their .text attribute is being updated here, the textfields are nil at this point in time.
Evaluate passing the String objects retrieved from Graph API directly to CreateAccountVC & then using them to update the textfields.
Consider morphing existing implementation to something on these lines:
class CreateAccountVC: UIViewController {
var fbName:String!
var fbEmail:String!
#IBOutlet weak var fullname: UITextField!
#IBOutlet weak var username: UITextField!
#IBOutlet weak var age: UITextField!
...
The snippet mentioned above here would change to:
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let vc = segue.destination as? CreateAccountVC
vc!.fbName = self.fbName
vc!.fbEmail = self.fbEmail
...

Firebase Auth creating users

I can't seem to get this to work. The database portion works and I'm getting user info as intended in the database, but it is not creating users in Firebase Auth. For the following code, it printed "can't register."
Can someone please tell me what I'm doing wrong?
import UIKit
import Firebase
import FirebaseAuth
class AddUserTableViewController: UITableViewController, UITextFieldDelegate {
#IBOutlet weak var firstNameTextField: UITextField!
#IBOutlet weak var emailTextField: UITextField!
#IBAction func saveUserButton(_ sender: Any) {
let ref: FIRDatabaseReference!
ref = FIRDatabase.database().reference()
FIRAuth.auth()?.createUser(withEmail: emailTextField.text!, password: "pass", completion: { (user, error) in
if error != nil {
print ("Can't Register")
}
else {
print ("I don't know what this means")
}
})
ref?.child("Users").childByAutoId().setValue(["First Name": self.firstNameTextField.text, "Email": self.emailTextField.text])
}
Just include Firebase, you don't need to include FirebaseAuth as well on each page.
Here's my working code for FireBase login, I did this from a Youtube tutorial a few weeks ago.
import UIKit
import Firebase
class LoginController: UIViewController {
#IBOutlet weak var menuButton:UIBarButtonItem!
#IBOutlet weak var signinSelector: UISegmentedControl!
#IBOutlet weak var signinLabel: UILabel!
#IBOutlet weak var emailTextField: UITextField!
#IBOutlet weak var passwordTextField: UITextField!
#IBOutlet weak var signinButton: UIButton!
var isSignIn:Bool = true
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func signinSelectorChanged(_ sender: UISegmentedControl) {
//Flip the boolean true to false
isSignIn = !isSignIn
//Check the boolean and set the buttons and labels
if isSignIn {
signinLabel.text = "Sign In"
signinButton.setTitle("Sign In", for: .normal)
}
else {
signinLabel.text = "Register"
signinButton.setTitle("Register", for: .normal)
}
}
#IBAction func signinButtonTapped(_ sender: UIButton) {
//Do some form validation on email and password
if let email = emailTextField.text, let pass = passwordTextField.text
{
//Check if it's signed or register
if isSignIn {
//Sign in the user with Firebase
Auth.auth().signIn(withEmail: email, password: pass, completion: { (user, error) in
//Check that user isn't nil
if let u = user {
//User is found, goto home screen
self.performSegue(withIdentifier: "goToHome", sender: self)
}
else{
//Error: Check error and show message
}
})
}
else {
//Register the user with Firebase
Auth.auth().createUser(withEmail: email, password: pass, completion: { (user, error) in
//Check that user isn't NIL
if let u = user {
//User is found, goto home screen
self.performSegue(withIdentifier: "goToHome", sender: self)
}
else {
//Check error and show message
}
})
}
}
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
//Dismiss the keyboard when the view is tapped on
emailTextField.resignFirstResponder()
passwordTextField.resignFirstResponder()
}
}

Custom Twitter Parse Login in Swift

I want to create custom view controller twitter Parse login. I do not want to use default "loginViewController" fields provided by Parse. I also want to extract user's screen name and profile picture from twitter and save it in Parse. Here is my code.
//SignInController for custom Parse SignIn
import UIKit
import Foundation
import Parse
import ParseUI
class SignInController: UIViewController {
#IBOutlet weak var fbLogin: UIButton! //Facebook login button
#IBOutlet weak var TwitterLogin: UIButton! //Twitter login button
#IBOutlet weak var username: UITextField!
#IBOutlet weak var password: UITextField!
#IBOutlet weak var SignIn: UIButton! //Custom SignIn button for Parse
#IBOutlet weak var signUp: UIButton! //Custom SignUp button for Parse
var actInd: UIActivityIndicatorView=UIActivityIndicatorView (frame: CGRectMake(0, 0, 150, 150)) as UIActivityIndicatorView
override func viewDidLoad() {
super.viewDidLoad()
//Do additional setup after loading the view.
self.actInd.center=self.view.center
self.actInd.hidesWhenStopped=true
self.actInd.activityIndicatorViewStyle=UIActivityIndicatorViewStyle.Gray
view.addSubview(self.actInd)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
//Dispose any resourses that can be recreated.
}
#IBAction func FBLoginAction(sender: AnyObject) {
//Facebook login
}
#IBAction func TwitterLoginAction(sender: AnyObject) {
//Here I want to implement twitter login
}
//Custom Parse SignIn
#IBAction func SignInAction(sender: AnyObject) {
var usernamefield=self.username.text
var passwordfield=self.password.text
if (count(usernamefield.utf16)<4 || count(passwordfield.utf16)<5)
{
alert("Invalid", message: "Username must be greater than 4 and password must be greater than 5")
}
else
{
self.actInd.startAnimating()
PFUser.logInWithUsernameInBackground(usernamefield, password: passwordfield, block: { (user, error) -> Void in
self.actInd.stopAnimating()
if((user) != nil)
{
self.alert("Success", message: "Logged In")
}
else
{
self.alert("Error", message: "\(error)")
}
})
}
}
//Create Account or SignUp Controller
class CreatAccount: UIViewController {
#IBOutlet weak var username: UITextField!
#IBOutlet weak var email: UITextField!
#IBOutlet weak var password: UITextField!
#IBOutlet weak var confirmPassword: UITextField!
#IBOutlet weak var signUp: UIButton!
var actInd: UIActivityIndicatorView=UIActivityIndicatorView (frame: CGRectMake(0, 0, 150, 150)) as UIActivityIndicatorView
override func viewDidLoad() {
super.viewDidLoad()
//Do additional setup after loading the view.
self.actInd.center=self.view.center
self.actInd.hidesWhenStopped=true
self.actInd.activityIndicatorViewStyle=UIActivityIndicatorViewStyle.Gray
view.addSubview(self.actInd)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
//Dispose any resourses that can be recreated.
}
//Custom Parse SignUp
#IBAction func signUpAction(sender: AnyObject) {
var usernamefield=self.username.text
var passwordfield=self.password.text
var emailfield=self.email.text
var confirmpasswordfield=self.confirmPassword.text
if (count(usernamefield.utf16)<4 || count(passwordfield.utf16)<5 || count(confirmpasswordfield.utf16)<5 )
{
alert("Invalid", message: "Username must be greater than 4 and password must be greater than 5")
}
else if(count(emailfield.utf16)<8)
{
alert("Invalid", message: "Please enter a valid email")
}
else if(passwordfield != confirmpasswordfield )
{
alert("Invalid", message: "Passwords mismatch")
}
else
{
self.actInd.startAnimating()
var newUser=PFUser()
newUser.username=usernamefield
newUser.password=passwordfield
newUser.email=emailfield
newUser.signUpInBackgroundWithBlock({ (succeed, error) -> Void in
self.actInd.stopAnimating()
if((error) != nil )
{
self.alert("Invalid", message: "\(error)")
}
else
{
self.alert("Success", message: "Signed Up")
}
})
}
}
Here is my answer for my question. Check TwitterLoginAction.
import UIKit
import Foundation
import Parse
import ParseUI
class SignInController: UIViewController
{
#IBOutlet weak var fbLogin: UIButton!
#IBOutlet weak var TwitterLogin: UIButton!
#IBOutlet weak var username: UITextField!
#IBOutlet weak var password: UITextField!
#IBOutlet weak var SignIn: UIButton!
#IBOutlet weak var signUp: UIButton!
var actInd: UIActivityIndicatorView=UIActivityIndicatorView (frame: CGRectMake(0, 0, 150, 150)) as UIActivityIndicatorView
override func viewDidLoad() {
super.viewDidLoad()
//Do additional setup after loading the view.
self.actInd.center=self.view.center
self.actInd.hidesWhenStopped=true
self.actInd.activityIndicatorViewStyle=UIActivityIndicatorViewStyle.Gray
view.addSubview(self.actInd)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
//Dispose any resourses that can be recreated.
}
#IBAction func FBLoginAction(sender: AnyObject) {
}
#IBAction func TwitterLoginAction(sender: AnyObject) {
PFTwitterUtils.logInWithBlock { (user, error) -> Void in
if (user==nil) {
println(user)
println("Uh oh. The user cancelled the Twitter login.")
return;
} else if ((user?.isNew) != nil) {
println("User signed up and logged in with Twitter!")
} else {
println("User logged in with Twitter!")
}
}
}
//Parse SignIn
#IBAction func SignInAction(sender: AnyObject) {
var usernamefield=self.username.text
var passwordfield=self.password.text
if (count(usernamefield.utf16)<4 || count(passwordfield.utf16)<5)
{
alert("Invalid", message: "Username must be greater than 4 and password must be greater than 5")
}
else
{
self.actInd.startAnimating()
PFUser.logInWithUsernameInBackground(usernamefield, password: passwordfield, block: { (user, error) -> Void in
self.actInd.stopAnimating()
if((user) != nil)
{
self.alert("Success", message: "Logged In")
}
else
{
self.alert("Error", message: "\(error)")
}
})
}
}
}
Here is the code for Twitter Login in Swift 3
PFTwitterUtils.logIn { (user, error) in
if (user==nil) {
print("Uh oh. The user cancelled the Twitter login.")
} else if ((user?.isNew) != nil) {
print("User signed up and logged in with Twitter!")
} else {
print("User logged in with Twitter!")
}
}

Resources