Firebase AuthUI returns nil for display name and email in Sign in with Apple - swift

When I try to sign in with Apple, Firebase AuthUI returns nil for display name and email. Here's my code
lazy var authUI: FUIAuth? = {
let UIAuth = FUIAuth.defaultAuthUI()
UIAuth?.delegate = self
UIAuth?.shouldHideCancelButton = true
return UIAuth
}()
func presentLogin(){
// providers
var providers: [FUIAuthProvider] = [
FUIEmailAuth(),
FUIGoogleAuth(),
FUIFacebookAuth()
]
if #available(iOS 13.0, *) {
let appleProvider = FUIOAuth.appleAuthProvider()
providers.append(appleProvider)
}
self.authUI?.providers = providers
let loginController = self.authUI!.authViewController()
present(loginController, animated: true, completion: nil)
}
func authUI(_ authUI: FUIAuth, didSignInWith authDataResult: AuthDataResult?, error: Error?) {
print(authDataResult?.user.displayName)
}

I had the same issue! I don't have the Apple sign in, but even just with Firebase it would show nil for this information. My issue was that I hadn't properly set up the data for Firebase and Xcode to talk. You code seems right, but it looks like you might be missing a few things..? You're more experienced than me, so I might be wrong! But here's my code...
// SIGN UP FUNCTION, first name, last name, email, password
let db = Database.database().reference()
func signUp(firstName: String, lastName: String, email: String, password: String, completion: #escaping (LocalUser?, Error?) -> Void) {
let usersRef = db.child("users")
Auth.auth().createUser(withEmail: email, password: password) {[weak self] (result, error) in
if let uid = result?.user.uid {
let newUser: [String: String] = ["firstName": firstName, "lastName": lastName, "email": email]
let newLocalUser = LocalUser(firstName: firstName, lastName: lastName, email: email)
usersRef.child(uid).setValue(newUser){(error: Error?, ref: DatabaseReference) in
completion(newLocalUser, error)
}
} else {
completion(nil, nil)
}
}
}
// SIGN IN FUNCTION, email, password
func signIn(email: String, password: String, completion: #escaping (LocalUser?, Error?) -> Void) {
let usersRef = db.child("users")
Auth.auth().signIn(withEmail: email, password: password) { [weak self]
(result, error) in
guard let user = result?.user else {
completion(nil, error)
return
}
let uid = user.uid
usersRef.child(uid).observeSingleEvent(of: .value) { (snapshot) in
let value = snapshot.value as? [String: Any]
if let user = value {
let userObject = LocalUser.makeObjectFrom(user)
newUser = userObject
completion(userObject, nil)
} else {
completion(nil, error)
}
}
}
}
I didn't see a reference to the db and uid, so this may help!

Related

"Flag" / Report user functionality to work — Swift / Xcode / Firebase

I'm trying to allow a user to report a user (in a Tinder-like app). To report, this button takes the user to a new VC to elaborate the issue as an email.
What I'm missing:
How can I add the reporter's and reportee's Firebase unique ID to the email (or whatever form of communication)? (So then I can investigate and take action as needed)
Here's what I have:
The code to properly send an email...
func configureMailController() -> MFMailComposeViewController {
let mailComposerVC = MFMailComposeViewController()
mailComposerVC.mailComposeDelegate = self
mailComposerVC.setToRecipients(["RadiusAppHelp#gmail.com"])
mailComposerVC.setSubject("Reporting user")
mailComposerVC.setMessageBody("Please include as much detail as possible:", isHTML: false)
return mailComposerVC
}
func showMailError() {
let sendMailErrorAlert = showAlert(withTitle: "Could not send message", message: "Please try again")
let dismiss = UIAlertAction(title: "Okay", style: .default, handler: nil)
// sendMailErrorAlert.addAction(dismiss)
// self.present(sendMailErrorAlert, animated: true, completion: nil)
}
func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
controller.dismiss(animated: true, completion: nil)
}
}
The code to pull the other user's ID in the swipe view VC...
var otherUsersId = ""
var currentlyViewedUserId: String?
firebaseServer.fetchUsers {[weak self] (usersDict) in
self?.usersDict = usersDict
let fetchedUsers = Array(usersDict.values)
self?.filterBlockedUsers(from: fetchedUsers)
self?.loadFirstUser()
self?.cardView.reloadData()
}
func loadFirstUser() {
if users.count > 0 {
let imageView = UIImageView()
let storage = Storage.storage()
let storageRef = storage.reference(withPath:
"\(users[0].userId!)/photos/\(0)")
currentlyViewedUserId = users[0].userId
PhotoUploader.downloadImageUrl(from:
storageRef) { (url) in
guard let url = url else { return }
imageView.downloaded(from: url,
contentMode: .scaleAspectFill)
}
nameLbl.text = users[0].firstName
setupDetailsFor(user: users[0])
infoCollectionView.reloadData()
}
}
As well as the code to block a user (but blocking / reporting functions work independently).
Any help is greatly appreciated!
Okay, I found at least a temporary fix...
(Not using Firestore however, which I'll eventually need to implement — https://www.youtube.com/watch?v=Ofux_4c94FI)
In FirebaseFunctions.swift...
// Report Someone
func reportSomeone(with userId: String, completion:
#escaping (Error?) -> Void) {
let usersRef = db.child("users")
if let uid = Auth.auth().currentUser?.uid {
usersRef.child("\(uid)/report/\ .
(userId)").setValue(true) { (error, dbref) in
completion(error)
}
}
}
// Set Preferences for Reporting
func reportPreferences(with userId: String,
completion: #escaping (Error?) -> Void) {
let usersRef = db.child("users")
if let uid = Auth.auth().currentUser?.uid {
usersRef.child("\(uid)/preferences/\ .
(userId)").setValue(true) { (error, dbref) in
completion(error)
}
}
}
In User.swift...
var report: [String: Bool]? = [:]
func makeDictionary() -> [String: Any] {
print("")
return [
"report": report ?? [:]
]
static func makeObjectFrom(_ dictionary: [String:
Any]) -> LocalUser {
let report = dictionary["report"] as?
[String:Bool] ?? [:]
}
let localUser = LocalUser(report: report)
In the View Controller...
import Firebase
var currentUserId = Auth.auth().currentUser?.uid
var otherUsersId = ""
// Report Button
var isCurrentUserReported = false
var isOtherUserReported = false
var currentlyViewedUserId: String?
// FILTER REPORTED USERS
func filterReportUsers(from users: [LocalUser]) {
var notReportUsers = users
var notReportUsersDict = self.usersDict
var reportUsers = newUser.report ?? [:]
if let currentUserId =
Auth.auth().currentUser?.uid {
reportUsers[currentUserId] = true
}
for (userId, report) in reportUsers ?? [:] {
print("UserId...", userId)
print("UserHere...", usersDict[userId])
if let user = usersDict[userId] {
notReportUsersDict.removeValue(forKey:
userId)
}
}
let notReport = Array(notReportUsersDict.values)
self.users = notReport
}
This isn't perfect, but it works!

''Value of type 'AuthDataResult?' has no member 'uid'''

#IBAction func SignUpBtn_TouchUpInside(_ sender: Any) {
Auth.auth().createUser(withEmail: emailTextField.text!, password: passwordTextField.text!, completion: { (user: AuthDataResult?, error:Error?) in
if error != nil{
print(error?.localizedDescription)
return
}
let ref = Database.database().reference()
let usersRenfence = ref.child("users")
let uid = user.uid
//(HERE IS WRONG, I DONT KNOW WHAT SHOULD I DO. It's my first time study code.)
let newUserRefernce = ref.child(uid)
newUserRefernce.setValue{["username": self.usernameTextField.text!, "email": self.emailTextField.text!]
print("description: \(newUserRefernce.description())")
Replace
let uid = user.uid
with
let uid = user!.user.uid
Look here in Docs

Save User's name in Firebase - Swift

I have three text field in my registration form. The e-mail id and password of the user are used by the Firebase SignUp method to create a new user. But I also want to save the user's name according to what they input.
My current code is;
#IBAction func registerPressed(_ sender: Any) {
SVProgressHUD.show(withStatus: "Setting you up")
dismissUIElements(value: false)
let currentUserName = userName.text
if currentUserName?.isEmpty == false {
FIRAuth.auth()?.createUser(withEmail: emailTextField.text!, password: passwordTextField.text!, completion: { (user, error) in
if error != nil {
print(error!)
SVProgressHUD.dismiss()
self.dismissUIElements(value: true)
} else {
print("Registration Successful!")
SVProgressHUD.dismiss()
self.dismissUIElements(value: true)
self.performSegue(withIdentifier: "goToSelectionFromRegister", sender: self)
}
})
}
else {
SVProgressHUD.dismiss()
SVProgressHUD.showError(withStatus: "Please enter your name!")
SVProgressHUD.dismiss(withDelay: 1)
self.dismissUIElements(value: true)
}
}
You need a function that will register the user and then create the child for that user in Firebase.
let databaseRef=//your path to users.
func registerUser(userUsername userName:String, userEmail email:String, userPassword password: String, userCreationComplete: #escaping (_ status: Bool, _ error: Error?) -> ()) {
Auth.auth().createUser(withEmail: email, password: password) { (user, error) in
guard let user = user else {
userCreationComplete(false, error)
return
}
let userData = ["userName": userName.text] as [String : Any]
ref.child(user.uid).updateChildValues(userData)
userCreationComplete(true, nil)
}
}
Then you call the function from within registerPressed() and you pass it the textfield values but make sure that none of them is empty.
You will create a new data table that stores that info. It won't be done in the create user function.
// create a reference to the DB
ref = Database.database().reference(fromURL: "https://your-project-name.firebaseio.com/")
//variables to store data
var myID : String?
var myName : String?
var myNumber : String?
var myEmail : String?
// creating the save user function
func saveUser(_ completion: #escaping(_ error: Error?) -> Void) {
if PageDataSource.sharedInstance.crudIsAvailable == true {
let usersRef = ref.child("users")
let myUserRef = usersRef.child(id)
myUserRef.updateChildValues(["User ID": id,
"Name": myName,
"Email": myEmail,
"Phone": .myNumber], withCompletionBlock: { (error, ref) in
if error != nil {
completion(error!)
} else {
completion(nil)
}
})
} else {
completion(NSError(domain: "Unavailable", code: 0, userInfo: nil))
}
}
// call the method like this to perform the save
func storeUser(completion: #escaping(_ completed: Bool, _ error: NSError?)-> Void) {
if let user = Auth.auth().currentUser {
myID = user.uid
myName = user.displayName
myEmail = user.email
// etc.,
completion(true,nil)
} else {
completion(false,NSError(domain: "No Current User", code: 1, userInfo: nil))
}
}

UserInfo={NSLocalizedDescription=The email address is already in use by another account., error_name=ERROR_EMAIL_ALREADY_IN_USE}

Hey guys actually i am trying two things here:- trying to create a new account and trying to open a screen like which appears after login but it is showing "email already exist error".
#IBAction func CreateAcccountButton(_ sender: AnyObject) {
guard let eventInterest = textBox.text,let email = EmailTestfield.text, let password = PasswordTestfield.text, let name = UsernameTestfield.text else {
print("Form is not valid")
return
}
Auth.auth().createUser(withEmail: email, password: password, completion: { (user, error) in
if let error = error {
print(error)
return
}
guard let uid = user?.uid else {
return
}
//successfully authenticated user
let imageName = UUID().uuidString
let storageRef = Storage.storage().reference().child("profile_images").child("\(imageName).png")
if let uploadData = UIImagePNGRepresentation(self.Profilepicture.image!) {
storageRef.putData(uploadData, metadata: nil, completion: { (metadata, error) in
if let error = error {
print(error)
return
}
print (metadata)
// let downloadURL = metadata?.downloadURL()
// print("URL ", downloadURL)
if let Profilepictureurl = metadata?.downloadURL()?.absoluteString {
let values = ["name": name, "email": email,"EventInterest":eventInterest,"Password":password,"Profilepictureurl": Profilepictureurl ]
let user = User(dictionary: values as [String : AnyObject])
let customViewController = MessagesController()
customViewController.setupNavBarWithUser(user)
customViewController.fetchUserAndSetupNavBarTitle()
// customViewController.navigationItem.title = values["name"] as? String
self.dismiss(animated: true, completion: nil)
self.registeruserintoDb(uid,values: values as [String : AnyObject])
}
})
}
}
)
}
fileprivate func registeruserintoDb(_ uid: String, values: [String: AnyObject]) {
let ref = Database.database().reference()
let usersReference = ref.child("users").child(uid)
usersReference.updateChildValues(values, withCompletionBlock: { (err, ref) in
if err != nil {
print(err!)
return
}
})
}
It's exactly what the error says, you already have a user with that email. Instead, use the auth.signIn method and check for currently signed in users.

Cannot convert value of type '(User?, _) -> ()' to expected argument type.i am struggling to resolve that error

Hey guys i am struggling to resolve this error actually i am trying to send these 4 strings and one picture to firebase and this was working fine until this error came up.
guard let email = emailTextField.text, let password = passwordTextField.text, let name = nameTextField.text else {
print("Form is not valid")
return
}
Auth.auth().createUser(withEmail: email, password: password, completion: { (user:User?, error) in
if error != nil {
print(error!)
return
}
guard let uid = user?.uid else {
return
}
//successfully authenticated user
let imageName = UUID().uuidString
let storageRef = Storage.storage().reference().child("profile_images").child("\(imageName).jpg")
if let profileImage = self.profileImageView.image, let uploadData = UIImageJPEGRepresentation(profileImage, 0.1) {
// if let uploadData = UIImagePNGRepresentation(self.profileImageView.image!) {
storageRef.putData(uploadData, metadata: nil, completion: { (metadata, error) in
if error != nil {
print(error!)
return
}
if let profileImageUrl = metadata?.downloadURL()?.absoluteString {
let values = ["name": name, "email": email, "profileImageUrl": profileImageUrl]
self.registerUserIntoDatabaseWithUID(uid, values: values as [String : AnyObject])
}
})
}
})
}
fileprivate func registerUserIntoDatabaseWithUID(_ uid: String, values: [String: AnyObject]) {
let ref = Database.database().reference()
let usersReference = ref.child("users").child(uid)
usersReference.updateChildValues(values, withCompletionBlock: { (err, ref) in
if err != nil {
print(err!)
return
}
If you write a type of user parameter (user: User?) you also have to write the types of other parameters (error: Error?)
Auth.auth().createUser(withEmail: email, password: password) { (user: User?, error: Error?)
in ...
}
Also you may write by this way:
Auth.auth().createUser(withEmail: email, password: password) { user, error in
...
}