如何全局访问结构的实例?

How do I access an instance of a struct globally?

我是编码新手,所以如果这是一个愚蠢的问题,请原谅。

我的应用程序有一个注册页面,然后是主屏幕。 在注册页面上,用户输入自己的姓名和电子邮件 ID 进行注册。当他这样做时,我使用以下结构来定义用户对象:

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

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

现在,这个用户对象是在注册视图中定义的,但我希望能够在全局范围内引用它的属性。 也就是说,在我的主页中,我希望能够包含一条消息:

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

我说的可能吗?

或者我应该使用结构以外的东西来全局访问我的用户结构的唯一保存实例吗?

对于这些情况,我喜欢使用 static/singleton current 用户。例如:

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
    }

}

这种方法的好处:

  1. 您可以在代码中的任何位置访问 User.current
  2. 您可以有多个用户,但只能有一个 当前 用户。这对于使用 Codable 进行解码非常重要。
  3. 您的代码更加简洁且不易出错。当你四处传递值时,你 运行 很可能会失去同步,并且你会添加很多不必要的混乱。此外,例如,当您依赖故事板进行转场时,传递值会变得很痛苦。
  4. 您将与用户相关的操作封装在一个纤薄的容器中 class。

您可以阅读有关单例设计模式的更多信息here

您可以将 User 上的属性声明为静态的,这样就可以在应用程序的任何位置访问该值。不过有一点需要注意,您一次不能拥有多个用户实例。

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

当您使用这些属性时,您可以直接在用户类型上访问它们。

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

print(User.email)
print(User.name)

只要我能看懂你的问题。注册完成后,您想在主屏幕(或其他几个地方)上访问 user 信息。您可以通过多种方式实现它,以下是其中两种。

只是为了让这个答案更具解释性,考虑 SignUP 屏幕由 SignUpViewController 表示,Home 屏幕正在表示通过 HomeViewController

通过传递值user

注册完成后即可通过。我确定一旦注册完成。您必须在注册屏幕的某处初始化 HomeViewControllerHomeViewControllerpushingpresenting

HomeViewController中定义一个属性(比方说user)类型的User 当您从注册屏幕初始化HomeViewController时,您只需需要在推送或显示 HomeViewController.

之前传递它

示例代码

// 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)"
   }
}

单例设计模式

如果你有一个用例,你可能在几个地方需要这个 user 属性 那么你可以创建一个单例 class 来保存这个 user信息。在该单例 class 中定义 user 属性 并在 SignUpViewControllerpushingpresenting HomeViewController 时设置它。

让我们假设 AppSession 是持有 user 属性

的单例 class
class AppSession {

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

    private init() { }
}

我们假设注册完成后调用下面的函数(在 SignUpViewController 中某处定义)

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

稍后,您可以像这样从任何地方访问它

class HomeViewController: UIViewController {

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

我希望它能让您有所了解,以便您可以根据您的用例实施上述任何一种方法。