0

I made a post request using Alamofire. This is my code to fetch data from server using an endpoint:

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

And this is the data i get from the server:

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

I want to save the response to UserDefault for further use. Help me to save the data to Userdefault and retrieve and print data.

Asif mimi
  • 93
  • 2
  • 11

4 Answers4

2

Create a model, a struct conforming to Codable

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

and extend 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)
    }
}

Now you can use auth(forKey:) and set(_:forKey:) to read and write an Auth instance directly.

Drop SwiftyJSON and change the Alamofire part to decode the JSON into the struct with 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)")
    }
}

To read the instance write

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

Update: Meanwhile Alamofire supports Codable natively

Alamofire.request("http://192.168.80.21:3204/api/auth/signin", method: .post, parameters: parameters).responseDecodable(of: Auth.self) {
    response in
    switch response.result {
    case .success(let auth):
        UserDefaults.standard.set(auth, forKey: "Auth")

    case .failure(let error):
        print("Error :- \(error)")
    }
}
vadian
  • 274,689
  • 30
  • 353
  • 361
0

If you use global variable. You can use save method according to your purpose which is written below :

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.")
            }
        }
    }
zeytin
  • 5,545
  • 4
  • 14
  • 38
0

accessToken

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
}

You can use the above func. like below.

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

Here,

Param: data is a generic parameter of type T. So here you need to pass the response data you get from server. (It should be Codable class type)

Param: AuthUser is

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

To get data:

 let data = getFromDefault(key: "userData", type: AuthUser.self)
 print(data)
Mahendra
  • 8,448
  • 3
  • 33
  • 56
-1

You can save JSON Model data in Userdefaults Using below function code

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

and retrive Data from Userdefaults use this function

func getData() -> yourModelData {
        var userDefaults = UserDefaults.standard
        let decoded  = userDefaults.data(forKey: "yourKey")
        let decodedData = NSKeyedUnarchiver.unarchiveObject(with: decoded) as! [yourModelData]
        return decodedData
    }
Dharman
  • 30,962
  • 25
  • 85
  • 135
Solayman Rana
  • 283
  • 3
  • 12