0

I am new to coding, so please forgive if this is a stupid question.

My app has a signUp page, followed by the homeScreen. On the signUp page, the user enters his name and email id to sign himself up. I have the following struct that I'm using to define a user object when he does so:

public struct User {
    let email: String
    let name: String
}

let user = User(email: "xyz@gmail.com", name: "Paul")

Now, this user object is defined in the signUp view, but I wish to be able to refer to its properties globally. That is, in my homePage, I wish to be able to include a message that says:

let welcomeMessage = "Welcome, \(user.name)"

Is what I'm saying possible?

Or should I be using something other than structs to globally access the one and only saved instance of my User struct?

Daniel
  • 3,188
  • 14
  • 34
  • 1
    It sounds like you are trying to save user data locally. If that is the case you should check [here](https://stackoverflow.com/questions/28628225/how-to-save-local-data-in-a-swift-app). The answer marked as correct was updated in 2019 so it should still be relevant. – BBSLIMS May 15 '20 at 16:18

3 Answers3

1

You could declare the properties on User to be static, which would then make the value accessible anywhere across the app. There is a caveat to this though, you cannot have more than one instance of a user at a time.

struct User {
    static var email: String?
    static var name: String?
}

When you use the properties, you would access them directly on the User type.

User.email = "john.doe@email.com"
User.name = "John Doe"

print(User.email)
print(User.name)
clawesome
  • 1,223
  • 1
  • 5
  • 10
0

For these kinds of situations, I like to use a static/singleton current User. For example:

struct User {

    private(set) static var current: User?

    let email: String
    let name: String

    static func login(name: String, email: String) {
        current = User(name: name, email: email)
    }

    // or you can even say:

    static func login(user: User) {
        current = user
    }

}

Benefits of this method:

  1. You can access User.current anywhere in your code.
  2. You can have multiple users, but only one current user. This is very important for decoding with Codable.
  3. Your code is more concise and bug-proof. When you pass values around, you run the high risk of falling out of sync, and you add a lot of unnecessary clutter. Moreover, passing values becomes painful when you rely on the storyboard for segues, for example.
  4. You encapsulate user-related operations in one slim class.

You can read more about the singleton design pattern here.

Daniel
  • 3,188
  • 14
  • 34
0

As long as I can understand your question. Once the signup is completed, you want to access that user information on the home screen( or maybe at several other places). You can achieve it in many ways, Below are two of them.

Just to make this answer more explanatory, consider SignUP screen is represented by SignUpViewController and Home screen is being represented by HomeViewController

By passing the value user

You can pass it once the signup is completed. I am sure once the sign up is completed. You must be initializing the HomeViewController somewhere in the SignUp screen and pushing or presenting the HomeViewController.

Define a property (let sayuser) type of User in HomeViewController When you initiale the HomeViewController from the signup screen, You just need to pass it before you push or present the HomeViewController.

Example code

// Your user struct

struct User {
    let email: String
    let name: String
}

class SignUpViewController: UIViewController {

    //This is just to show you, I am sure you must be initializing the user appropriately.

    let user = User(email: "xyz@gmail.com", name: "Paul")

    //Assuming you have a function which is called as soon signup is completed

    func didSignUpCompleted() {
        // initialise the HomeViewController, here I am assuming you have storyboard corresponding to HomeViewController
        let storyboard = UIStoryboard(name: "youstoryboarname", bundle: nil)
        let homeViewController =  storyboard.instantiateViewController(withIdentifier: "homeViewControllerIdentifier") as! HomeViewController
        // This is the point where you have to pass that user property to HomeViewController
        homeViewController.user  = user
        // If the viewcontroller is embeded in UINavigationController
        self.navigationController?.pushViewController(homeViewController, animated: true)
    }
}


class HomeViewController: UIViewController {
    // this will be set from SignUp screen
    var user: User? 

   func viewDidLoad() {
       super.viewDidLoad()
       guard let signedUpUser = user else { return }
       let welcomeMessgae = "Welcome, \(signedUpUser.name)"
   }
}

Singleton Design Pattern

If you have a use case where you may be needed this user property at several places then you can create a singleton class that will hold this user information. Define the user property in that singleton class and set it when you pushing or presenting HomeViewController from SignUpViewController.

Let's assume that AppSession is the singleton class which holds the user property

class AppSession {

    static let current = AppSession()
    // user property. which will be set from sign up screen
    var user: User?

    private init() { }
}

Let's assume below function is called once sign-up is completed (defined somewhere in SignUpViewController)

func didSignUpCompleted() {
     // set the `user` 
     AppSession.current.user = User(email: "xyz@gmail.com", name: "Paul")
}

Later on, you can access it from anywhere like this

class HomeViewController: UIViewController {

   func viewDidLoad() {
       super.viewDidLoad()
       guard let signedUpUser = AppSession.current.user else { return }
       let welcomeMessgae = "Welcome, \(signedUpUser.name)"
   }
}

I hope it may give you a bit of understanding so that you can implement either of the mentioned approaches as per your use case.

Kamar Shad
  • 6,089
  • 1
  • 29
  • 56