我正在尝试通过用户成功登录后从API提取数据的结构将用户保存在UserDefaults中。
这是我的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
我的模型和视图模型符合Codable,我的资源也符合Codable。
T.type
不符合可编码协议的错误原因是什么?如何解决?
这种发送和接收数据的方法合适吗?
答案 0 :(得分:3)
对于类T
的{{1}}函数,您没有指定Encodable
应该是load(resource:...
更改此:
Webservice:
对此:
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")
但是另一个问题是:为什么要从JSON编码然后将其编码到PropertyList?为什么不将JSON数据保存在UserDefaults中?
答案 1 :(得分:0)
也许对您有用。
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)}