具有userdefaults的用户信息单例返回nil

时间:2017-10-05 21:20:12

标签: ios swift

我正在尝试将用户信息存储到userDefaults并将其分配给singleton。我在成功调用API后保存信息。我确信它可以保存所有这些值。但由于某种原因,单身人士返回nil。

这是我的用户类:

class User {
    var id: Int
    var name: String
    var email: String
    var profile_image_url: String
    var token: String

    init(id: Int, name: String, email: String, profile_image_url: String, token: String) {
        self.id = id
        self.name = name
        self.email = email
        self.profile_image_url = profile_image_url
        self.token = token
    }

    init?(dict: [String: JSON]) {
        guard let id = dict["id"]?.intValue,
            let name = dict["name"]?.stringValue,
            let email = dict["email"]?.stringValue,
            let profile_image_url = dict["profile_image_url"]?.stringValue,
            let token = dict["token"]?.stringValue
            else{ return nil }

        self.id = id
        self.name = name
        self.email = email
        self.profile_image_url = profile_image_url
        self.token = token

    }

    class var sharedInstance: User {
        struct Singleton {
            static var instance : User = {
                let userDefaults = UserDefaults.standard
                let keychain = KeychainSwift()
                let user = User(
                    id: userDefaults.integer(forKey: "user_id"),
                    name: userDefaults.string(forKey: "name")!,
                    email: userDefaults.string(forKey: "email")!,
                    profile_image_url: userDefaults.string(forKey: "profile_image_url")!,
                    token: keychain.get("token")!
                )
                return user
            }()
        }

        return Singleton.instance
    }
}

这就是我在API调用后保存值的方法:

class func saveUserData(user_id: Int, name: String, email: String, profile_image_url: String, token:String) {
        let userDefaults = UserDefaults.standard
        let keychain = KeychainSwift()
        keychain.clear()
        userDefaults.set(user_id, forKey: "user_id")
        userDefaults.set(name, forKey: "name")
        userDefaults.set(email, forKey: "email")
        userDefaults.set(profile_image_url, forKey: "profile_image_url")

        keychain.set(token, forKey: "token")

    }

我做错了什么,甚至是正确的做法?

1 个答案:

答案 0 :(得分:1)

正如我所提到的,如果你在Swift 4中编码,你应该利用Codable协议。使您的用户成为符合Codable的结构。如果需要,您可以提供User struct自定义编码密钥(不是必需的)。添加一种方法将用户数据保存到用户默认值,并创建一个易错的初始化程序,以便从中读取用户数据:

struct User: Codable {
    let id: Int
    let name: String
    let email: String
    let profileImageUrl: String
    let token: String
    init(id: Int, name: String, email: String, profileImageUrl: String, token: String) {
        self.id = id
        self.name = name
        self.email = email
        self.profileImageUrl = profileImageUrl
        self.token = token
    }

    func saveToDefaults() -> Bool {
        let encoder = JSONEncoder()
        do {
            let json = try encoder.encode(self)
            UserDefaults.standard.set(json, forKey: "User\(id)Key")
            return true
        } catch {
            print(error)
            return false
        }
    }
    init?(data: Data) {
        do {
            self = try JSONDecoder().decode(User.self, from: data)
        } catch {
            print(error)
            return nil
        }
    }
    init?(id: Int) {
        guard let data = UserDefaults.standard.data(forKey: "User\(id)Key") else { return nil }
        self.init(data: data)
    }
}

游乐场测试

let user = User(id: 1, name: "a name", email: "name@email.com", profileImageUrl: "https://i.stack.imgur.com/Xs4RX.jpg", token: "anyTokenString")

if user.saveToDefaults() {
    print("success")
    if let user = User(id: 1) {
        print(user.id)
        print(user.name)
        print(user.email)
        print(user.profileImageUrl)
        print(user.token)
    } else {
        print("there is no user with id 1")
    }
}

这将打印

  

成功

     

1

     

名称

     

name@email.com

     

https://i.stack.imgur.com/Xs4RX.jpg

     

anyTokenString