this is my code I want the user name not to have spaces and lowercase
example (wizkhalifa)
func textField(_ textFieldToChange: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if textFieldToChange == username {
let characterSetNotAllowed = CharacterSet.whitespaces
if let _ = string.rangeOfCharacter(from:NSCharacterSet.uppercaseLetters) {
return false
}
if let _ = string.rangeOfCharacter(from: characterSetNotAllowed, options: .caseInsensitive) {
return false
} else {
return true
}
}
if UserNameField.text != nil, emailField.text != nil, passwordField.text != nil, rePassword.text != nil && passwordField.text == rePassword.text {
Auth.auth().createUser(withEmail: emailField.text!, password: passwordField.text!, completion: { (user, error) in
if error != nil {
AlertController.showAlert(self, titel: "Error", message: " Fill all fields \nUser exists ")
return
}
You need to check 2 things and you can put that check in the method called when trying to create a user, and/or when the user is typing.
First check, spaces :
if let text = UserNameField.text {
if text.components(separatedBy: " ").count > 1 && text.lowercased() != textField.text {// add your other tests on this line
// the text is in lowercase without space character and your tests pass
Auth.auth().createUser(withEmail: emailField.text!, password: passwordField.text!, completion: { (user, error) in
// check if there is an error
})
} else {
AlertController.showAlert(self, titel: "Error", message: " Fill all fields \nUser exists ")
}
Here is the version for OP with his code :
if UserNameField.text != nil, emailField.text != nil, passwordField.text != nil, rePassword.text != nil && passwordField.text == rePassword.text && UserNameField.text.components(separatedBy: " ").count <= 1 && UserNameField.text.lowercased() == UserNameField.text {
Auth.auth().createUser(withEmail: emailField.text!, password: passwordField.text!, completion: { (user, error) in
if error != nil {
AlertController.showAlert(self, title: "Error", message: " Fill all fields \nUser exists ")
return
} else {
// all good
}
})
} else {
AlertController.showAlert(self, title: "Error", message: " Fill all fields \nUser exists ")
}
Related
I tried literally tried every possible option to write it, but I can't seem to figure out the solution.
func signup(email: String, password: String) {
Auth.auth().createUser(withEmail: emailText.text!, password: passwordText.text!, completion: { (user, error) in
if error != nil {
print(error!)
}else {
self.createProfile(user!) //Here's the problem described in the title //
let homePVC = RootPageViewController()
self.present(homePVC, animated: true, completion: nil)
}
})
}
func createProfile(_ user: User) {
let newUser = ["email": user.email, "photo": "https://firebasestorage.googleapis.com/v0/b/ecoapp2.appspot.com/o/photos-1.jpg?alt=media&token=ee104f2d-ed9a-4913-8664-04fd53ead857"]
self.databaseRef.child("profile").child(user.uid).updateChildValues(newUser) { (error, ref) in
if error != nil {
print(error!)
return
}
print("Profile successfully created")
}
}
You need
Auth.auth().createUser(withEmail: email, password: password) { authResult, error in
// ...
guard let user = authResult.user else { reurn }
self.createProfile(user)
}
func createProfile(_ user: FIRUser ) { --- }
Starting from Firebase API 5.0 it's createUser() method returns FIRAuthDataResultCallback instead of User object directly.
In your case you can fix it my making following changes:
func signup(email: String, password: String) {
Auth.auth().createUser(withEmail: emailText.text!, password: passwordText.text!, completion: { (user, error) in
if error != nil {
print(error!)
}else {
self.createProfile(user!.user) //Here's how you can fix it
let homePVC = RootPageViewController()
self.present(homePVC, animated: true, completion: nil)
}
})
}
For more code readability I would replace your code like below:
func signup(email: String, password: String) {
Auth.auth().createUser(withEmail: emailText.text!, password: passwordText.text!, completion: { (authResult, error) in
if error != nil {
print(error!)
}else {
self.createProfile(authResult!.user)
let homePVC = RootPageViewController()
self.present(homePVC, animated: true, completion: nil)
}
})
}
I´m trying to check for signup errors and if textFields is empty. This is kind of working, but it allows the user to register the user if the nameTextFieldand the addressTextFieldis empty. The alert poops up correctly though.
#IBAction func registerButton(_ sender: UIButton) {
Auth.auth().createUser(withEmail: emailTextField.text!, password: passwordTextField.text!, completion: { user, error in
if error != nil {
if let errCode = AuthErrorCode(rawValue: error!._code) {
switch errCode {
case .invalidEmail:
self.errorMsg(title: "Error", message: "E-mail address format wrong")
case .emailAlreadyInUse:
self.errorMsg(title: "Error", message: "E-mail is already in use")
case .weakPassword:
self.errorMsg(title: "Error", message: "Weak password. Need at least 6 characters")
default:
print("Create User Error: \(error!)")
}
}
return
} else {
//Display errormsg for missing entry
if (self.nameTextField.text?.isEmpty)! {
self.missingText(title: "Ooops", message: "Please enter your name")
if (self.addressTextField.text?.isEmpty)! {
self.missingText(title: "Ooops", message: "Please enter your address")
}
} else {
//Register userinfo in Firebase
let ref = Database.database().reference()
let usersRefrence = ref.child("users")
let uid = user?.user.uid
let newUserRefrence = usersRefrence.child(uid!)
newUserRefrence.setValue(["Name": self.nameTextField.text!, "Address": self.addressTextField.text!])
}
self.registrationConfirmation(title: "Great", message: "Please sign in with the registered user")
}
})
}
validate textfield before going to auth.
guard let email = emailTextField.text, email.isValidEmail(), let password = passwordTextField.text, password != "" else {
// show error for nil values
return
}
// go with Autth
Auth.auth().createUser(withEmail: email, password: password, completion
make an extension for validating email
extension String {
func isValidEmail() -> Bool {
// here, `try!` will always succeed because the pattern is valid
let regex = try! NSRegularExpression(pattern: "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+#[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$", options: .caseInsensitive)
return regex.firstMatch(in: self, options: [], range: NSRange(location: 0, length: count)) != nil
}
}
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))
}
}
Recently my facebook login hasn't been working. It doesn't save into my database but in Firebase authentication it shows someone signed in with facebook but the email is blank. It doesn't save any data to my database which it should. The email is returning nil. My google sign in works. I've checked all the connections and they all seem to be fine. (I could have missed something) anyone have any suggestions on what connections I should check? Not sure what to do...
More Info
I printed my graph request... not sure if this helps to debug
let loginManager: FBSDKLoginManager = FBSDKLoginManager()
loginManager.logIn(withReadPermissions: self.facebookPermissions, from: self, handler: { (result, error) in
if error != nil {
loginManager.logOut()
let message: String = "An error has occured. \(String(describing: error))"
let alertView = UIAlertController(title: "Alert", message: message, preferredStyle: UIAlertControllerStyle.alert)
alertView.addAction(UIAlertAction(title: "Ok ", style: UIAlertActionStyle.default, handler: nil))
self.present(alertView, animated: true, completion: nil)
} else if (result?.isCancelled)! {
// user cancelled login
loginManager.logOut()
} else {
let accessToken = FBSDKAccessToken.current()
guard let accessTokenString = accessToken?.tokenString else { return }
let credential = FacebookAuthProvider.credential(withAccessToken: accessTokenString)
Auth.auth().signIn(with: credential) { (user, error) in
if (error != nil) {
// handle error
print(error ?? "Error")
} else {
let ref = Database.database().reference()
// guard for user id
guard let uid = user?.uid else {
return
}
let usersReference = ref.child("user_profiles").child(uid)
let graphRequest : FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me", parameters: ["fields": "id, name, email"])
graphRequest.start(completionHandler: { (connection, result, error) -> Void in
if error != nil {
// Process error
print("Error: \(String(describing: error))")
} else {
guard let data: [String:AnyObject] = result as? [String:AnyObject] else {
print("Can't pull data from JSON")
return
}
guard let userName: String = data["name"] as? String else {
print("Can't pull username from JSON")
return
}
guard let userID: String = data["id"] as? String else {
print("Can't pull ID from JSON")
return
}
let imgURLString = "http://graph.facebook.com/\(userID)/picture?type=large" as String
guard let userEmail: String = data["email"] as? String else {
print("Can't pull email from JSON")
print("Error: \(String(describing: error))")
return
}
// initial # posts = 0
let values = ["name": userName, "email": userEmail, "facebookID": userID, "profPicString": imgURLString] as [String : Any]
// update database with new user
usersReference.updateChildValues(values, withCompletionBlock: { (err, ref) in
// error in database save
if err != nil {
print(err ?? "Error saving user to database")
return
}
})
}
})
self.dismiss(animated: false, completion: nil)
// Present the main view
if let viewController = self.storyboard?.instantiateViewController(withIdentifier: "Customer Profile") {
UIApplication.shared.keyWindow?.rootViewController = viewController
self.dismiss(animated: true, completion: nil)
}
}
}
}
})
Using Swift 5 I found the email inside providerData which is an array of FIRUserInfo:
if AccessToken.current != nil {
let credential = FacebookAuthProvider.credential(withAccessToken: AccessToken.current!.tokenString)
Auth.auth().signIn(with: credential) { (res, err) in
if err != nil || res == nil {
//...
return
}
guard let providerData = res?.user.providerData else {
//...
return
}
for firUserInfo in providerData {
print(firUserInfo.providerID)
print(firUserInfo.email ?? "Email not found")
}
}
}
#IBAction func signup(_ sender: Any) {
print("began signup process")
guard let fullname = fullnameField.text, fullname != "" else {
print("FULLNAME field is empty")
return
}
guard let username = usernameField.text, username != "" else {
print("USERNAME field is empty")
return
}
guard let email = emailField.text, email != "" else {
print("EMAIL field is empty")
return
}
guard let password = passwordField.text, password != "" else {
print("PASSWORD field is empty")
return
}
print("all fields good")
mainActivityIndicator.startAnimating()
self.checkUsernameAvailability(username: username, completion: {
result in
print("starting check")
...
})
print("finished the function")
}
The issue is basically that nothing inside of the checkUsernameAvailability function will call.
The console looks like this:
began signup process
all fields good
finished the function
it does not print 'starting check' or run any code at all inside of the function.
This is probably a rookie error and I am sorry if it is a stupid question.
Future thanks.
P.S I checked the entire console and there is no error relating to this.
EDIT: Here is the code inside the function
func checkUsernameAvailability(username: String, completion: #escaping (Bool) -> Void) {
_ = Database.database().reference().child("usernames").observe(.childAdded, with: {
snapshot in
print("checking username availability")
print(snapshot)
completion(true)
let dict = snapshot.value as? [String: AnyObject]
for handled in (dict?.values)! {
print("stumbled")
print(handled)
if username.lowercased() == handled.lowercased {
completion(false)
}
}
})
}
And...
self.checkUsernameAvailability(username: username, completion: {
result in
print("starting check")
if result == false {
print("username is taken")
self.mainActivityIndicator.stopAnimating()
return
} else {
Auth.auth().createUser(withEmail: email, password: password, completion: {
(user, error) in
if error != nil {
print(error ?? "ERROR OCCURED")
self.mainActivityIndicator.stopAnimating()
return
}
let ref = Database.database().reference()
ref.child("~/users/\(user?.uid ?? "0")/username").setValue(username.lowercased())
ref.child("~/users/\(user?.uid ?? "0")/fullname").setValue(fullname)
ref.child("usernames/\(user?.uid ?? "0")").setValue(username.lowercased())
self.mainActivityIndicator.stopAnimating()
})
}
})
The Database.database().reference().child("usernames").observe call simply never calls the with block. I would assume that block is called when the event .childAdded is observed, but I see no code that would add a child. To me this looks like you are setting up an asynchronous observer, so this code will not run when you make the call, it will run when the monitored event takes place.