将结构加载并保存到UserDefaults中



我正试图将用户保存在UserDefaults中,该结构在用户成功登录时从API获取数据。

这是我的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()

}
}

这是我的模型类:

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

这是我的视图模型:

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

我就是这样称呼它的:

let login = LoginUser(email: email, password: password)
let vm = UserViewModel(loginUser: login)
Webservice().load(resource: User.create(vm: vm), caller: self) { (result) in

我的模型和视图模型符合可编码,我的资源也是可编码的。

T.type不符合协议Encodable的错误原因是什么?如何解决?

这种发送和接收数据的方法合适吗?

对于Webservice:类的load(resource:...函数,您没有指定T应该是Encodable

更改此项:

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

对此:

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

此外,您还需要对值进行编码,而不是这里的泛型类型:

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

应该是

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

但另一个问题是:为什么要从JSON进行编码,然后将其编码到PropertyList?为什么不将JSON数据保存在UserDefaults中?

可能对您有用。

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

这是如何存储

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

最新更新