changing the value for label - swift

I've create a login page with functions well but after logging in I want the user to be able to confirm his/her data every time they use the login
The problem is I can Get the email address into another UIViewController but I cant change the text of my label which shows the email and it says unwrapping nil ....
import Foundation
import UIKit
class userIdConfirmationViewController : UIViewController {
var emailHolder = String()
#IBOutlet var emailConfirmation: UILabel!
#IBOutlet var nameConfirmation: UITextField!
#IBOutlet var usernameConfirmation: UITextField!
override func viewDidLoad() {
//here is the Error
emailConfirmation.text = emailHolder
}
#IBAction func ConfirmationButton(sender: UIButton) {
let email = emailConfirmation.text
let name = nameConfirmation.text
let username = usernameConfirmation.text
print (" email : \(email) name : \(name) username : \(username)" )
}
}

Related

How to retrieve and show user data from Firebase with swift?

I followed a tutorial to create a register and login screen with firebase and is already working, but now I want to create the screen "My account" with text fields where show the name, mail, etc.. of the user, so my question and I need help is how to get the data from firebase and show that information on that screen, how can I do it please?
I already read the firebase documentation https://firebase.google.com/docs/auth/ios/manage-users but I don't know how to proceed because Im learning programming/swift and I have to still improving my level
I attach the code of the sign up view
import UIKit
import FirebaseAuth
import FirebaseFirestore
import Firebase
class SignUpViewController: UIViewController {
#IBOutlet weak var nameField: UITextField!
#IBOutlet weak var lastNameField: UITextField!
#IBOutlet weak var emailField: UITextField!
#IBOutlet weak var passwordField: UITextField!
#IBOutlet weak var signUpButton: UIButton!
#IBOutlet weak var errorLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
setUpElements()
}
func setUpElements(){
//Hide the error label
errorLabel.alpha = 0
//Style the elements
Utilities.styleTextField(nameField)
Utilities.styleTextField(lastNameField)
Utilities.styleTextField(emailField)
Utilities.styleTextField(passwordField)
Utilities.styleFilledButton(signUpButton)
}
// Check the fields and validate that the data is correct. If everything is correct, this method returns nil. Otherwise, it returns the error message
func validateFields() -> String? {
// Check that all fields are filled in
if nameField.text?.trimmingCharacters(in: .whitespacesAndNewlines) == "" ||
lastNameField.text?.trimmingCharacters(in: .whitespacesAndNewlines) == "" ||
emailField.text?.trimmingCharacters(in: .whitespacesAndNewlines) == "" ||
passwordField.text?.trimmingCharacters(in: .whitespacesAndNewlines) == "" {
return "Please fill in all fields."
}
// Check if the password is secure
let cleanedPassword = passwordField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
if Utilities.isPasswordValid(cleanedPassword) == false {
// Password isn't secure enough
return "Please make sure your password is at least 8 characters, contains a special character and a number."
}
return nil
}
#IBAction func signUpTapped(_ sender: Any) {
// Validate the fields
let error = validateFields()
if error != nil {
// There's something wrong with the fields, show error message
showError(error!)
}
else {
// Create cleaned versions of the data
let firstName = nameField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
let lastName = lastNameField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
let email = emailField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
let password = passwordField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
// Create the user
Auth.auth().createUser(withEmail: email, password: password) { (result, err) in
// Check for errors
if err != nil {
// There was an error creating the user
self.showError("Error creating user")
}
else {
// User was created successfully, now store the first name and last name
let db = Firestore.firestore()
db.collection("users").addDocument(data: ["firstname":firstName, "lastname":lastName, "uid": result!.user.uid ]) { (error) in
if error != nil {
// Show error message
self.showError("Error saving user data")
}
}
// Transition to the home screen
self.transitionToHome()
}
}
}
}
func showError(_ message:String) {
errorLabel.text = message
errorLabel.alpha = 1
}
func transitionToHome() {
let homeViewController = storyboard?.instantiateViewController(identifier: Constants.Storyboard.homeViewController) as? HomeViewController
view.window?.rootViewController = homeViewController
view.window?.makeKeyAndVisible()
}
}
And the actual code of my account view controller, just I add it the text fields, I don't know how to proceed
import UIKit
class MyAccountViewController: UIViewController {
#IBOutlet weak var nameField: UITextField!
#IBOutlet weak var lastnameField: UITextField!
#IBOutlet weak var emailField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}
I think that I provided all the info necessary, thank you

displaying user email on viewcontroller gives optional"email adress" [duplicate]

This question already has answers here:
How to remove optional text from json Result In swift
(3 answers)
Optional Text in Alert in ResetPassword - iOS Project using Swift
(2 answers)
Closed 1 year ago.
So I'm using firebase Authentication in my ios app, and I want to display the email address, and Username in UIlabels on a viewcontroller. But when i display the value of Auth.auth().email on a UIlabel, the Label would show Optional"email adress".How do i get rid of the Optional and also how to allow the user to have a display name in firebase Authentication?
import Firebase
import FirebaseAuth
class ProfileViewController: UIViewController {
#IBOutlet weak var profiepic: UIImageView!
#IBOutlet weak var UsernameLabel: UILabel!
#IBOutlet weak var EmailLabel: UILabel!
#IBOutlet weak var league: UILabel!
#IBOutlet weak var Achievements: UIButton!
#IBOutlet weak var resetpasswd: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
UsernameLabel.layer.borderColor = UIColor.black.cgColor
EmailLabel.layer.borderColor = UIColor.black.cgColor
league.layer.borderColor = UIColor.black.cgColor
Achievements.layer.cornerRadius = 55/2
resetpasswd.layer.cornerRadius = 55/2
resetpasswd.layer.borderColor = UIColor.black.cgColor
displayinfo()
}
func displayinfo() {
let user = Auth.auth().currentUser
if let user = user {
// The user's ID, unique to the Firebase project.
// Do NOT use this value to authenticate with your backend server,
// if you have one. Use getTokenWithCompletion:completion: instead.
let email = user.email
let photoURL = user.photoURL
EmailLabel.text = "Email: \(email)"
// ...
}
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
}
*/
}
You need to use if or guard to display string info properly.
Using if:
func displayinfo() {
let user = Auth.auth().currentUser
if let user = user {
if let email = user.email {
EmailLabel.text = "Email: \(email)"
}
if let photoURL = user.photoURL {
...
}
// ...
}
}
Using guard:
func displayinfo() {
guard let user = Auth.auth().currentUser else {
print("No user info found")
return
}
if let email = user.email {
EmailLabel.text = "Email: \(email)"
//EmailLabel.text = "Email: " + email
}
if let photoURL = user.photoURL {
...
}
// ...
}
Let me know if you have any issue in these solutions.
Apart from this, I would rather write UIViewController in this manner which seems to be a more clearer approach.
class ProfileViewController: UIViewController {
#IBOutlet weak var profiepic: UIImageView!
#IBOutlet weak var lblUsername: UILabel! {
didSet {
lblUsername.layer.borderColor = UIColor.black.cgColor
}
}
#IBOutlet weak var lblEmail: UILabel! {
didSet {
lblEmail.layer.borderColor = UIColor.black.cgColor
}
}
#IBOutlet weak var lblLeague: UILabel! {
didSet {
lblLeague.layer.borderColor = UIColor.black.cgColor
}
}
#IBOutlet weak var btnAchievements: UIButton! {
didSet {
btnAchievements.layer.cornerRadius = 55/2
// For button height, instead of 55 here you can use, btnAchievements.bounds.height / 2 or use constrain also to change button height when bound changes
}
}
#IBOutlet weak var btnReset: UIButton! {
didSet {
btnReset.layer.cornerRadius = 55/2
btnReset.layer.borderColor = UIColor.black.cgColor
}
}
private var currentUser: AuthUser? {// Type of Auth.auth().currentUser
didSet {
// Use above code for displayInfo or simply call displayInfo from here
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.currentUser = Auth.auth().currentUser
}
...
}
I hope this would help you designing other UIViewControllers as well.

How can I show the localized description of an error in an error label format to a user in Swift?

I'm very new to Swift, and Instead of just printing the localized description of an error when a user attempts to register for an app, I want to show it in an error label to the user. However, I get the error "Expression is not assignable: function call returns immutable value." I'm not sure what this means or what I should be doing differently in order to show the default description for the error.
class RegisterViewController: UIViewController {
#IBOutlet weak var emailTextfield: UITextField!
#IBOutlet weak var passwordTextfield: UITextField!
#IBOutlet weak var errorLabel: UILabel!
override func viewDidLoad() {
errorLabel.isHidden = true
}
#IBAction func registerPressed(_ sender: UIButton) {
if let email = emailTextfield.text, let password = passwordTextfield.text {
Auth.auth().createUser(withEmail: email, password: password) { authResult, error in
if let e = error {
self.errorLabel.isHidden = false
String(e.localizedDescription) = self.errorLabel.text!
"Expression is not assignable: function call returns immutable value"
} else {
//Navigate to ChatViewController
self.performSegue(withIdentifier: "RegisterToChat", sender: self)
}
}
}
}
}
The assignment must be the other way round. You are going to assign always the right side to the left side.
And you don’t need to create a string from a string
self.errorLabel.text = e.localizedDescription

Secure text .echosbullets not working for password field

Here's what I've got:
#IBOutlet weak var password: NSSecureTextField!
#IBOutlet weak var shwpswd: NSButton! //Checkbox
#IBOutlet weak var pswdcell: NSSecureTextFieldCell! //Cell
#IBAction func shwpswd(_ sender: Any) {
if(shwpswd.state == 1) {
pswdcell.echosBullets = false // Turn the Secure text into regular text
}
else if(shwpswd.state == 0) {
pswdcell.echosBullets = true // Secure text
}
}
Everything seems to run fine, except the text in the password field doesn't change states between echoing bullets and echoing the real text. Everything is linked together properly too - Cell is within the text field, password button is in the view and the outlet works. I'm wondering if this is another one of the "Swift on mac < Swift on iOS cases".
EDIT: Here is the final solution, should anyone care to see it:
#IBOutlet weak var shwpswd: NSButton! //Checkbox
#IBOutlet weak var visPswd: NSTextfield! //hidden regular box to show chars
#IBOutlet weak var password: NSSecureTextField! //visible initial secure box
#IBAction func shwpswd(_ sender: Any) {
if(shwpswd.state == 1) {
self.visPswd.stringValue = self.password.stringValue //Sync both the text fields
self.password.isHidden = true //hide the secure field
self.visPswd.isHidden = false //show the real character echo field
}
else if(shwpswd.state == 0) {
self.password.stringValue = self.visPswd.stringValue //Sync the two
self.password.isHidden = false // Inverse of above
self.visPswd.isHidden = true
}
}
Note the text fields password and visPswd are the same size and position in the view - one remains hidden at all times to avoid overlapping. When the user enters values in either the password or visPswd field, it syncs with the other field when the checkbox state is changed.
You can accomplish what you want adding a second text field in top of your secure field. Add an IBAction to your check box to switch your fields isHidden property and copy the other textField stringValue and make it the first responder. Your implementation should look like something like this:
import Cocoa
class ViewController: NSViewController {
#IBOutlet weak var password: NSSecureTextField!
#IBOutlet weak var showPassword: NSTextField!
#IBOutlet weak var shwpswd: NSButton!
override func viewDidLoad() {
super.viewDidLoad()
shwpswd.state = .off
showPassword.isHidden = true
}
override func viewDidAppear() {
super.viewDidAppear()
password.window?.makeFirstResponder(password)
}
#IBAction func showHidePassword(_ sender: NSButton) {
showPassword.isHidden.toggle()
password.isHidden.toggle()
if !showPassword.isHidden {
showPassword.stringValue = password.stringValue
showPassword.becomeFirstResponder()
} else {
password.stringValue = showPassword.stringValue
password.becomeFirstResponder()
}
}
}
show/hide password sample

Despite multiple unwrapping attempts, fatal error: unexpectedly found nil while unwrapping an Optional value

I have been practicing a login page and the creation of an account with Firebase. I am successfully signing up a user and saving the user in firebase. Now I am trying to save a first and last name to the user id when they create their account. I've tried looking at other SO answers, but still can't seem to get this to work.
I have been going through multiple tutorials, and have tried multiple unwrapping attempts, but keep running into this error. Below is my view controller:
View Controller
import UIKit
import Firebase
class ViewController: UIViewController {
var ref: DatabaseReference!
#IBOutlet weak var emailTextField: UITextField!
#IBOutlet weak var passwordTextField: UITextField!
#IBOutlet weak var firstNameField: UITextField!
#IBOutlet weak var lastNameField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
var ref = Database.database().reference()
}
#IBAction func createAccountTapped(_ sender: Any) {
if let email = emailTextField.text, let password = passwordTextField.text, let firstName = firstNameField.text, let lastName = lastNameField.text {
Auth.auth().createUser(withEmail: email, password: password ) { (user, error) in
// ...
if let firebaseError = error {
print(firebaseError.localizedDescription)
return
//add popup later
}
let userId = user!.uid
self.ref.child("users").child(userId).setValue(["firstName": firstName])
print("User registered in Firebase with a userId of " + user!.uid)
}
}
}
Where am I going wrong? I thought I was unwrapping the variables at the top, with my 'if let'. I tried force unwrapping them individually, as well, but keep having the same error. A bit lost.
in viewDidLoad(), you call
var ref = Database.database().reference()
but it should be
ref = Database.database().reference()
Swift is treating it like a different variable that you're declaring within the scope of viewDidLoad(), so when you go to use ref, it still has no value.
Please change your Database reference from
var ref: DatabaseReference!
to
var databaseRef = Database.database().reference()
and then do
self.child("users").child(userId).setValue(["firstName": firstName])
or in you viewDidLoad do
self.ref = Database.database().reference()
This error happens because you are not initialising your Database reference
This should work without any problems
import UIKit
import Firebase
import FirebaseDatabase
class ViewController: UIViewController {
var ref: DatabaseReference!
#IBOutlet weak var emailTextField: UITextField!
#IBOutlet weak var passwordTextField: UITextField!
#IBOutlet weak var firstNameField: UITextField!
#IBOutlet weak var lastNameField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
self.ref = Database.database().reference()
}
#IBAction func createAccountTapped(_ sender: Any) {
if let email = emailTextField.text, let password = passwordTextField.text, let firstName = firstNameField.text, let lastName = lastNameField.text {
Auth.auth().createUser(withEmail: email, password: password ) { (user, error) in
// ...
if let firebaseError = error {
print(firebaseError.localizedDescription)
return
//add popup later
}
let userId = user!.uid
self.ref.child("users").child(userId).setValue(["firstName": firstName])
print("User registered in Firebase with a userId of " + user!.uid)
}
}
}