首页 > 解决方案 > 尽管使用了用户默认值,为什么我的单例类在重建时无法保留信息?

问题描述

我需要创建一个 MyPerson 结构来存储 firstName 和 lastName 属性,我需要在全局范围内保存和访问它们。在任何给定时间,我只有一个“人”。

现在,虽然我已经设法使我的 person 实例可以在全球范围内访问,但这仍然不会在构建中持续存在。我究竟做错了什么?

另外,如果有人能在效率和准确性方面批评我的代码,我将非常感激,我正在尝试学习 Swift 和 SwiftUI,而不是尝试对所有事情都使用变通方法!

struct MyPerson {
    var firstName: String {
        didSet {
            UserDefaults.standard.set(firstName, forKey: "fn")
        }
    }
    var lastName: String {
        didSet {
            UserDefaults.standard.set(lastName, forKey: "ln")
        }
    }

    init(first: String, last: String) {
        self.firstName = first
        self.lastName = last
    }
}

class Global {

    static let global = Global()

    var person: MyPerson?

    private init() { }
}



struct Home: View {

var body: some View {
Button(action: {

            Global.global.person = MyPerson(first: "John", last: "Doe")                
        }) {
            Text("BUTTON")
        }
   }
   }


struct Home2: View {

var body: some View {
Button(action: {

            guard let user = Global.global.person else {return}
            print(user.firstName)

        }) {
            Text("BUTTON")
        }
   }
   }

标签: swiftstructsingletonswiftui

解决方案


您正在写入 UserDefaults,但从不读取它们。要在构建中保留此人,您需要检查以前是否已保存名称。

编辑: 观察者didSet不是从初始化程序调用的,因此在初始化值时必须单独编写字段。由于您使用结构来保存MyPerson数据,因此我建议将它们更改为let属性。

可能是这样的:

struct MyPerson {

    let firstName: String
    let lastName: String

    init(first: String, last: String) {
        self.firstName = first
        self.lastName = last

        UserDefaults.standard.set(firstName, forKey: "fn")
        UserDefaults.standard.set(lastName, forKey: "ln")
    }

    /// Failable initializer that checks for a previously-saved MyPerson
    init?() {
        guard let first = UserDefaults.standard.string(forKey: "fn"),
            let last = UserDefaults.standard.string(forKey: "ln") else {
                return nil
        }

        self.init(first: first, last: last)
    }
}


class Global {

    ...

    private init() {
        if let person = MyPerson() {
            self.person = person
        }
    }
}

因此,在您将全局人员设置为John Doe一次后Home,下次启动应用程序时,您应该会在Home2.


推荐阅读