如何在 Swift 中将 JSON 数据保存到 UserDefault? [复制]

Posted

技术标签:

【中文标题】如何在 Swift 中将 JSON 数据保存到 UserDefault? [复制]【英文标题】:How to save the JSON data to UserDefault in Swift? [duplicate] 【发布时间】:2020-10-28 07:09:32 【问题描述】:

我使用 Alamofire 发出了一个帖子请求。这是我使用端点从服务器获取数据的代码:

    Alamofire.request("http://192.168.80.21:3204/api/auth/signin", method: .post, parameters: parameters,encoding: JSONEncoding.default, headers: nil).responseJSON 
        response in
        switch response.result 
        case .success(let value):
            let json = JSON(value)
            print(json)

            break
        case .failure(let error):
            print("Error :- \(error)")
        
    
  

这是我从服务器获取的数据:


  "accessToken" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6NTIsInJvbGUiOjEsImlhdCI6MTYwMzg2ODUxNCwiZXhwIjoxNjAzOTU0OTE0fQ.y68w8XQfqFZDVgaxiuFuVCOqaI5e5vZ-SfoDB_Ctxro",
  "role" : "admin",
   "auth" : true

我想保存对 UserDefault 的响应以供进一步使用。帮助我将数据保存到 Userdefault 并检索和打印数据。

【问题讨论】:

【参考方案1】:

创建一个模型,一个符合Codable的结构体

struct Auth: Codable 
    let accessToken, role: String
    let auth: Bool

并扩展UserDefaults

extension UserDefaults 
    func auth(forKey defaultName: String) -> Auth? 
        guard let data = data(forKey: defaultName) else  return nil 
        do 
            return try JSONDecoder().decode(Auth.self, from: data)
         catch  print(error); return nil 
    

    func set(_ value: Auth, forKey defaultName: String) 
        let data = try? JSONEncoder().encode(value)
        set(data, forKey: defaultName)
    

现在您可以使用auth(forKey:)set(_:forKey:) 直接读写Auth 实例。

删除 SwiftyJSON 并更改 Alamofire 部分以将 JSON 解码为带有 JSONDecoder 的结构

Alamofire.request("http://192.168.80.21:3204/api/auth/signin", method: .post, parameters: parameters).responseData 
    response in
    switch response.result 
    case .success(let data):
        do  
            let auth = try JSONDecoder().decode(Auth.self, from: data)
            print(auth)
            UserDefaults.standard.set(auth, forKey: "Auth")
         catch  print(error) 

    case .failure(let error):
        print("Error :- \(error)")
    

读取实例写入

let auth = UserDefaults.standard.auth(forKey: "Auth")

【讨论】:

【参考方案2】:

访问令牌

func setInDefault<T: Codable>(key: String, type: T.Type, data: T?) 
    
    guard let data = data else 
        return
    

    do 
        let encoder = JSONEncoder()
        let encodeData = try encoder.encode(data)
        let dict:[String:Any] = try JSONSerialization.jsonObject(with: encodeData, options: .allowFragments) as! [String : Any]
        
        let data = NSKeyedArchiver.archivedData(withRootObject: dict)

        //set user data in defaults
        UserDefaults.standard.set(data, forKey: key)
        UserDefaults.standard.synchronize()
     catch 
        print(error)
        //handle error
    


func getFromDefault<T: Codable>(key: String, type: T.Type) -> T? 

    let archieved = UserDefaults.standard.value(forKey: key)
    let dict = NSKeyedUnarchiver.unarchiveObject(with: archieved as? Data ?? Data())
    let decoder = JSONDecoder()
    do 
        if let dic = dict 
            let data = try JSONSerialization.data(withJSONObject: dic, options: .prettyPrinted)
            return try decoder.decode(type, from: data)
        
        
     catch 
        print(error)
         //handle error
    
    return nil

你可以使用上面的函数。如下所示。

setInDefault(key: "userData", type: AuthUser.self, data: data)

这里,

Param:dataT 类型的通用参数。所以在这里你需要传递你从服务器获得的响应数据。 (应该是Codable类类型)

参数:AuthUser

struct AuthUser : Codable 

  let accessToken : String?
  let role: String?
  let auth: Bool?

  enum CodingKeys: String, CodingKey 
    case accessToken = "accessToken"
    case role = "role"
    case auth = "auth"
  

  init(from decoder: Decoder) throws 
    let values = try decoder.container(keyedBy: CodingKeys.self)
    accessToken = try values.decodeIfPresent(String.self, forKey: .accessToken)
    role = try values.decodeIfPresent(String.self, forKey: .role)
    auth = try values.decodeIfPresent(Bool.self, forKey: .auth)
  

获取数据:

 let data = getFromDefault(key: "userData", type: AuthUser.self)
 print(data)

【讨论】:

Param:data是要存储的数据。你能清除这个吗 请检查已编辑的答案。 请注意,在大多数情况下类型参数不是必需的,至少您可以使用默认值type: T.Type = T.self【参考方案3】:

如果你使用全局变量。您可以根据您的目的使用save 方法,如下所示:

let objects = [yourObjectClass]()

        func save() 
            let jsonEncoder = JSONEncoder()
            if let savedData = try? jsonEncoder.encode(objects)  
                let defaults = UserDefaults.standard    
                defaults.set(savedData, forKey: "objects") 
             else 
                print("Failed to save objects.")
            
        
    

【讨论】:

【参考方案4】:

您可以使用下面的函数代码将 JSON 模型数据保存在 Userdefaults 中

 func saveData(data: yourModelData)
        var userDefaults = UserDefaults.standard
        let encodedData: Data = NSKeyedArchiver.archivedData(withRootObject: yourModelData)
        userDefaults.set(encodedData, forKey: "yourKey")
        userDefaults.synchronize()
        
    
 

并从 Userdefaults 中检索数据使用此函数

func getData() -> yourModelData 
        var userDefaults = UserDefaults.standard
        let decoded  = userDefaults.data(forKey: "yourKey")
        let decodedData = NSKeyedUnarchiver.unarchiveObject(with: decoded) as! [yourModelData]
        return decodedData
    

【讨论】:

以上是关于如何在 Swift 中将 JSON 数据保存到 UserDefault? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

如何在 swift 2 中将 UITextField 保存到核心数据?

如何在 Swift 中将 CGImage 保存到数据中?

如何在 Swift 中将 JSON 转换为数据类型?

如何在 Swift 中将可转换属性保存到 Core Data

如何在 iOS Swift 中将选定的 tableView 单元格保存到数组中?

如何在 Swift 中将绘图保存到 tableview?