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

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.

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

How do I store a calculated result in UserDefaults to display in a "results" View controller [duplicate]

This question already has answers here:
How can I use UserDefaults in Swift?
(14 answers)
Closed 4 years ago.
First time poster so sorry for the incorrect format/length of the question.
I am building an app in Xcode that allows users to input various inputs among numerous view controllers and then have output in a single view controller with results displayed through labels.
The raw inputted textfield data is stored into UserDefaults and can display them later in the resulting VC with no problem. Im having trouble with calculated outputs (in this example "papiresult") however.
Can anyone provide guidance how to print out the calculated result several view controllers later using UserDefaults?
This is the rough layout
Here is the code I have in the first ViewController:
import UIKit
let userDefaults = UserDefaults()
var papiresult = Double()
class ViewController1: UIViewController, UITextFieldDelegate {
#IBOutlet weak var textField1: UITextField!
#IBOutlet weak var textField2: UITextField!
#IBOutlet weak var textField3: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
textField1.delegate = self
textField2.delegate = self
textField3.delegate = self
}
//Declaring data input into UserDefaults//
#IBAction func sendDataToVC2(_ sender: Any) {
let systPA = Double(textField1.text!)
let diastPA = Double(textField2.text!)
let cvPressure = Double(textField3.text!)
papiresult = ((systPA!-diastPA!)/cvPressure!)
userDefaults.set(textField1.text, forKey: "PASP")
userDefaults.set(textField2.text, forKey: "PADP")
userDefaults.set(textField3.text, forKey: "CVP")
userDefaults.set(papiresult, forKey: "PAPI")
}
}
Here is the code in the last (result) view controller:
import UIKit
class ViewController3: UIViewController {
#IBOutlet weak var label1: UILabel!
#IBOutlet weak var label2: UILabel!
#IBOutlet weak var label3: UILabel!
#IBOutlet weak var label4: UILabel!
#IBOutlet weak var label5: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
//Recalling data from UserDefaults//
override func viewWillAppear(_ animated: Bool) {
if let data1 = userDefaults.object(forKey: "PASP") {
if let message1 = data1 as? String {
self.label1.text = message1}
}
if let data2 = userDefaults.object(forKey: "PADP") {
if let message2 = data2 as? String {
self.label2.text = message2}
}
if let data3 = userDefaults.object(forKey: "CVP") {
if let message3 = data3 as? String {
self.label3.text = message3}
}
if let data4 = userDefaults.object(forKey: "Age") {
if let message4 = data4 as? String {
self.label4.text = message4}
}
if let data5 = userDefaults.object(forKey: "PAPI") {
if let message5 = data5 as? Double {
self.label5.text = "\(message5)"}
}
}
Basically, you should use UserDefaults.standard rather than creating a new instance of UserDefaults class. So I think this code
let userDefaults = UserDefaults()
should be replaced with this:
let userDefaults = UserDefaults.standard

Xcode 8 - Swift 3 OS X- Refresh custom View Controller

I am creating an application in Xcode 8 and Swift 3 for use at my place of employment. I am going to give you a brief understanding of what I am doing, and what I am attempting to do. So in my program I load data about the computer, including MAC address and IP Address, which I have working flawlessly. My issue is when I try to refresh the data, it either crashes or does not reload anything.
Now I have read the documentation that specifically says "Do not call viewDidLoad()" but I am not sure how else to reload the data. I have been working on this one little feature for a while, but unfortunately I am still coming up blank and cannot find much more information.
Basically I pull the information and then write them to labels which present the data to the technician. I have attempted to use the refresh function under the view controller, as well as the reload under the first response to no avail. Does anyone have any ideas that I can attempt to reload the data on button click?
Edit 2:
import Cocoa
import Foundation
import NetFS
class ViewController: NSViewController {
// Hostname outlet
#IBOutlet weak var populateHostname: NSTextField!
// IP Address 1 outlet
#IBOutlet weak var populateIPAddr: NSTextField!
#IBOutlet weak var IPAdap1: NSTextField!
// IP Address 2 outlet
#IBOutlet weak var populateIPAddr2: NSTextField!
#IBOutlet weak var IPAdap2: NSTextField!
// MAC Adress 1 outlet
#IBOutlet weak var populateMACAddress: NSTextField!
#IBOutlet weak var MACAdap1: NSTextField!
// MAC Address 2 outlet
#IBOutlet weak var populateMACAddress2: NSTextField!
#IBOutlet weak var MACAdap2: NSTextField!
// OS Version outlet
#IBOutlet weak var osVersion: NSTextField!
// Buttons
#IBOutlet weak var editLoginConfigButton: NSButton!
#IBAction func refresh(_ sender: AnyObject) {
//ViewController.setNeedsDisplay
reloadData()
}
#IBAction func EditLoginConfig(_ sender: AnyObject) {
*Omitted from code - for stackoverflow*
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
loadData()
}
func reloadData() {
//get adapters - includes IP, Adapter Name, and MAC Address
let myInterfaces = getInterfaces()
//ip address
if (myInterfaces.count != 0) {
populateIPAddr.stringValue = myInterfaces[0].addr
IPAdap1.stringValue = myInterfaces[0].name
if (myInterfaces.count != 1) {
if (myInterfaces[0].addr != myInterfaces[1].addr) {
populateIPAddr2.stringValue = myInterfaces[1].addr
IPAdap2.stringValue = myInterfaces[1].name
}
} else {
populateIPAddr2.stringValue = ""
IPAdap2.stringValue = ""
}
}
//mac address
if (myInterfaces.count != 0) {
populateMACAddress.stringValue = myInterfaces[0].mac
MACAdap1.stringValue = myInterfaces[0].name
if (myInterfaces.count != 1) {
if (myInterfaces[0].mac != myInterfaces[1].mac) {
populateMACAddress2.stringValue = myInterfaces[1].mac
MACAdap2.stringValue = myInterfaces[1].name
}
} else {
populateMACAddress2.stringValue = ""
MACAdap2.stringValue = ""
}
}
}
func loadData() {
//hostname
let currentHost = Host.current().localizedName ?? ""
populateHostname.stringValue = currentHost
//get adapters - includes IP, Adapter Name, and MAC Address
let myInterfaces = getInterfaces()
//ip address
if (myInterfaces.count != 0) {
populateIPAddr.stringValue = myInterfaces[0].addr
IPAdap1.stringValue = myInterfaces[0].name
if (myInterfaces.count != 1) {
if (myInterfaces[0].addr != myInterfaces[1].addr) {
populateIPAddr2.stringValue = myInterfaces[1].addr
IPAdap2.stringValue = myInterfaces[1].name
}
} else {
populateIPAddr2.stringValue = ""
IPAdap2.stringValue = ""
}
}
//mac address
if (myInterfaces.count != 0) {
populateMACAddress.stringValue = myInterfaces[0].mac
MACAdap1.stringValue = myInterfaces[0].name
if (myInterfaces.count != 1) {
if (myInterfaces[0].mac != myInterfaces[1].mac) {
populateMACAddress2.stringValue = myInterfaces[1].mac
MACAdap2.stringValue = myInterfaces[1].name
}
} else {
populateMACAddress2.stringValue = ""
MACAdap2.stringValue = ""
}
}
//OS X Version
let osVers = ProcessInfo.processInfo.operatingSystemVersion
let osMajorVers = String(osVers.majorVersion)
let osMinorVers = String(osVers.minorVersion)
let osPatchVers = String(osVers.patchVersion)
osVersion.stringValue = (osMajorVers + "." + osMinorVers + "." + osPatchVers)
// Edit Users Login Config enabled/disabled
if (NSUserName() == "Administrator" || NSUserName() == "administrator") {
// disable button
editLoginConfigButton.isEnabled = false
}
}
override var representedObject: AnyObject? {
didSet {
// Update the view, if already loaded.
}
}
}
So as I said before (I believe), using it like this does not break the thread, but it also does not refresh the data. Any idea where it is failing?

Disable button in cocoa application OS X

I would like to have the submit button enabled once some fields on a form have been validated. Currently the preview function works great, preview button provides the validation I need. Working on Xcode 7 and swift 2. I would really appreciated if someone can point me in the right direction. Below is the code I currently have:
import Cocoa
#NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
var projectFlag = false
var descriptionFlag = false
var releaseFlag = false
// Fields
#IBOutlet weak var projectNumberTextField:NSTextField!
#IBOutlet weak var projectDescriptionTextField:NSTextField!
#IBOutlet weak var releaseFolderNameTextField:NSTextField!
#IBOutlet weak var passwordTextField:NSTextField!
// Labels for preview
#IBOutlet weak var label1: NSTextField!
#IBOutlet weak var label2: NSTextField!
#IBOutlet weak var label3: NSTextField!
#IBOutlet weak var label4: NSTextField!
#IBOutlet weak var label5: NSTextField!
// Quit Button :: Quits the application
#IBAction func quitButton(sender: AnyObject) {
NSApplication.sharedApplication().terminate(self)
}
// Preview button behavior
#IBAction func previewButton(sender: AnyObject) {
// Project Number ::
let project = projectNumberTextField.stringValue
label1.stringValue = "\(project)"
if (label1.stringValue == "00-0000") {
label1.stringValue = "Project Number is not valid"
label1.textColor = NSColor.redColor()
projectFlag = false
} else {
label1.textColor = NSColor.blackColor()
projectFlag = true
}
// Project Description :: Name, 2016
let description = projectDescriptionTextField.stringValue
label2.stringValue = "\(description)"
if (label2.stringValue == "Name, 2016") {
label2.stringValue = "Enter a valid project description"
label2.textColor = NSColor.redColor()
descriptionFlag = false
} else {
label2.textColor = NSColor.blackColor()
descriptionFlag = true
}
// Folder Release Name :: RELEASE_NAME
let release = releaseFolderNameTextField.stringValue
label3.stringValue = "\(release)"
if (label3.stringValue == "RELEASE_NAME") {
label3.stringValue = "Enter a valid folder release name"
label3.textColor = NSColor.redColor()
releaseFlag = false
} else {
label3.textColor = NSColor.blackColor()
releaseFlag = true
}
// Password :: If needed
let password = passwordTextField.stringValue
label4.stringValue = "\(password)"
// Preview :: Code format for txt file
let preview = "\(project)|"+"\(description)|"+"\(release)|"+"\(password)/"
label5.stringValue = "\(preview)"
}
// Submit button behavior
#IBAction func submitButton(Sender: AnyObject) {
}
func applicationDidFinishLaunching(aNotification: NSNotification) {
// Insert code here to initialize your application
}
func applicationWillTerminate(aNotification: NSNotification) {
// Insert code here to tear down your application
}
}

swift save multiple manage objects

Having issues saving my manage objects within my code. For some reason when i place data in the first view controller everything works well. For instance
I place new categories such as "Fruits", "Dairy", "Meats". The first view controller takes the data. When I click on the specific item such as "Dairy", and put in "Milk" for items within that section. If I go back to the previous view controller and click on "Meats", I see the same data i put in under "Dairy". How do i properly manage my NSManage objects.
Here is my code below.
import UIKit
import CoreData
class HomeSpecificItemViewController: UIViewController {
var selectedItem : [Items] = []
#IBOutlet weak var itemNameTextField: UITextField!
#IBOutlet weak var brandNameTextField: UITextField!
#IBOutlet weak var caloriesTextField: UILabel!
#IBOutlet weak var priceTextField: UILabel!
#IBOutlet weak var amountTextField: UITextField!
#IBOutlet weak var threshHoldNumberField: UITextField!
#IBOutlet weak var stepper: UIStepper!
override func viewDidLoad() {
super.viewDidLoad()
stepper.wraps = true
stepper.autorepeat = true
stepper.maximumValue = 10
// Do any additional setup after loading the view.
}
#IBAction func saveButton(sender: AnyObject) {
let context = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
let itemDescription = NSEntityDescription.insertNewObjectForEntityForName("Items", inManagedObjectContext: context) as! Items
itemDescription.setValue(itemNameTextField.text, forKey: "Items")
itemDescription.setValue(brandNameTextField.text, forKey: "Items")
do {
try context.save()
}catch _ {
}
/*
let request = NSFetchRequest(entityName: "Items")
let results : [AnyObject]?
do {
results = try context.executeFetchRequest(request)
}catch _ {
results = nil
}
if results != nil {
self.itemDescription = results as! [Items]
}
*/
}
#IBAction func cancelPressed(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: nil)
}
#IBAction func increaseNumberStepper(sender: UIStepper) {
threshHoldNumberField.text = Int(sender.value).description
}
}
Do you have a specific view controller for each category? If so, what you have to do is add predicates to your more specific view controllers.
Something like:
var request = NSFetchRequest(entityName: "Food")
request.predicate = NSPredicate(format: "category == %#", "Meat")
meats = try! context.executeFetchRequest(request)
This would return an array of all Food objects whose category atribute holds the string "Meat".
I was saving my data to core data without properly declaring the manage context and without assigning the text labels to the core data object.
issue resolved!