简体   繁体   English

将结构加载并保存到 UserDefaults

[英]Load and save struct into UserDefaults

I am trying to save the user in UserDefaults from a struct that fetches the data from an API when a user logs in successfully.我正在尝试将用户保存在 UserDefaults 中,该结构在用户成功登录时从 API 获取数据。

Here is my Webservice class:这是我的 Web 服务类:

import Foundation
import UIKit

struct Resource<T: Codable> {

    let url : URL
    let httpMethod = HTTPMethod.post
    var body : Data? = nil
}

extension Resource {

    init(url: URL) {
        self.url = url
    }

}



enum HTTPMethod : String {
    case get = "GET"
    case post = "POST"
}

 enum NetworkingError: Error {
        case domainError
        case badResponse
        case encodingError
        case decodingError
    }


class Webservice {

    func load<T>(resource: Resource<T>, caller: UIViewController ,completion: @escaping (Result<T, NetworkingError>) -> Void) {

            var request = URLRequest(url: resource.url)
            request.httpMethod = resource.httpMethod.rawValue
            request.httpBody = resource.body
            request.addValue("application/JSON", forHTTPHeaderField: "Content-Type")

            URLSession.shared.dataTask(with: request) { (data, response, error) in


                guard let data = data, error == nil else {
                    return completion(.failure(.domainError))
                }

                let json = try? JSONSerialization.jsonObject(with: data, options: [])
                print(json)

                do {
                let result = try JSONDecoder().decode(T.self, from: data)

//save to UserDefaults

                    UserDefaults.standard.set(PropertyListEncoder().encode(T), forKey: "user")\\ here I am getting error that T.type does not conform to Encodable protocol.





completion(.success(result))


                }catch {


                    do {

                        if let result = try? JSONDecoder().decode(LoginErrorResponse.self, from: data){
                    print(result.errors.msg)
                        DispatchQueue.main.async {

                            let alert = AlertService().alert(message: "\(result.errors.msg[0])")
                            caller.present(alert, animated: true)

                        }
                        completion(.failure(.decodingError))
                    }

                        if let result = try? JSONDecoder().decode(SignUpErrorResponse.self, from: data){
                        print(result.errors.msg)
                            DispatchQueue.main.async {

                                let alert = AlertService().alert(message: "\(result.errors.msg)")
                                caller.present(alert, animated: true)

                            }
                            completion(.failure(.decodingError))
                        }

                }

            }





            }.resume()


        }

    }

Here is my model class:这是我的模型类:

import Foundation

struct User: Encodable, Decodable {

    let name: String
    let email: String
    let password: String
    let first_name: String
    let last_name: String
}

extension User {

    static var all : Resource<User> = {

        guard let url = URL(string: "http://orderahead.gagzweblab.xyz:3001/login") else {
                    fatalError("url is incorrect")
               }
        return Resource<User>(url: url)

    }()

    static func create(vm : UserViewModel) -> Resource<UserResponseModel?> {

        let user = User(vm)
        guard let url = URL(string: "http://orderahead.gagzweblab.xyz:3001/register") else {
             fatalError("url is incorrect")
        }
        guard let data = try? JSONEncoder().encode(user) else {
             fatalError("error encoding user")
        }

        var resource = Resource<UserResponseModel?>(url: url)
        resource.body = data

        return resource
    }

}

extension User {

    init?(_ vm: UserViewModel) {

         let email = vm.email
         let password = vm.password
        let first_name = vm.first_name
        let last_name = vm.last_name
        let name = vm.name

        self.password = password
        self.email = email
        self.first_name = first_name
        self.last_name = last_name
        self.name = name
    }
}

And here is my view model:这是我的视图模型:

import Foundation

struct UserViewModel : Codable {
    let user : User

}

extension UserViewModel {

    var name : String {
        return self.user.name
    }
    var email : String {
        return self.user.email
    }
    var password : String {
        self.user.password
    }
    var first_name: String {
        self.user.first_name
    }
    var last_name: String {
        self.user.last_name
    }

}

This is how I am calling it:我是这样称呼它的:

let login = LoginUser(email: email, password: password)
                   let vm = UserViewModel(loginUser: login)

Webservice().load(resource: User.create(vm: vm), caller: self) { (result) in

My model and view model conform to Codable as well as my Resource is Codable too.我的模型和视图模型符合 Codable 以及我的 Resource 也是 Codable。

What is the reason of the error that T.type does not conform to protocol Encodable? T.type不符合Encodable协议的错误原因是什么? How to resolve it?如何解决?

Is this approach to send and receive data appropriate?这种发送和接收数据的方法是否合适?

You didn't specify that T should be Encodable for load(resource:... function of class Webservice:您没有指定T应该是Encodable for load(resource:...Webservice:函数Webservice:

Change this:改变这个:

class Webservice {

  func load<T>(resource: Resource<T>, caller: UIViewController ,completion: @escaping (Result<T, NetworkingError>) -> Void) {

To this:对此:

class Webservice {

  func load<T: Encodable>(resource: Resource<T>, caller: UIViewController ,completion: @escaping (Result<T, NetworkingError>) -> Void) {

And also you need to encode value, not generic type here:而且您还需要对值进行编码,而不是这里的泛型类型:

UserDefaults.standard.set(PropertyListEncoder().encode(T.self), forKey: "user")

should be应该

UserDefaults.standard.set(try PropertyListEncoder().encode(result), forKey: "user")

But another question is: Why do you encode from JSON and then encode it to PropertyList?但另一个问题是:为什么要从 JSON 编码,然后将其编码为 PropertyList? Why not save JSON data in UserDefaults?为什么不在 UserDefaults 中保存 JSON 数据?

may be it will work for you.可能对你有用。

extension UserDefaults {

func save<T: Codable>(_ object: T, forKey key: String) {
    let encoder = JSONEncoder()
    if let encodedObject = try? encoder.encode(object) {
        UserDefaults.standard.set(encodedObject, forKey: key)
        UserDefaults.standard.synchronize()
    }
}

func getObject<T: Codable>(forKey key: String) -> T? {
    if let object = UserDefaults.standard.object(forKey: key) as? Data {
        let decoder = JSONDecoder()
        if let decodedObject = try? decoder.decode(T.self, from: object) {
            return decodedObject
        }
    }
    return nil
}}

this is how to store这是如何存储

func setCoableInUser<T: Codable>(_ object:T, key: String)-> Void{
UserDefaults.standard.save(object, forKey: key)}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM