如何使用Alamofire Router来组织API调用?(swift Alamofire5)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用Alamofire Router来组织API调用?(swift Alamofire5)相关的知识,希望对你有一定的参考价值。
我想把我的 AF请求 到 路由器 结构,使项目更简洁。我收到一个错误信息
协议类型'Any'的值不能符合'Encodable';只有structenumclass类型才能符合协议。
请帮我修正一下代码。THANK YOU!
我的URL将有一个占位符为 帐号 和 密码 将被送入 body
. 答复将是: Bool (success), username and bearer token
.
下面是我的 AF请求:
let username = usernameTextField.text
let password = passwordTextField.text
let loginParams = ["password":"\(password)"]
AF.request("https://example.com/users/\(username)/login",
method: .post,
parameters: loginParams,
encoder: JSONParameterEncoder.default,
headers: nil, interceptor: nil).response response in
switch response.result
case .success:
if let data = response.data
do
let userLogin = try JSONDecoder().decode(UsersLogin.self, from: data)
if userLogin.success == true
defaults.set(username, forKey: "username")
defaults.set(password, forKey: "password")
defaults.set(userLogin.token, forKey: "token")
print("Successfully get token.")
else
//show alert
print("Failed to get token with incorrect login info.")
catch
print("Error: \(error)")
case .failure(let error):
//show alert
print("Failed to get token.")
print(error.errorDescription as Any)
到目前为止,我有什么可以转换为 AF路由器 结构。
import Foundation
import Alamofire
enum Router: URLRequestConvertible
case login(username: String, password: String)
var method: HTTPMethod
switch self
case .login:
return .post
var path: String
switch self
case .login(let username):
return "/users/\(username)/login"
var parameters: Parameters?
switch self
case .login(let password):
return ["password": password]
// MARK: - URLRequestConvertible
func asURLRequest() throws -> URLRequest
let url = try Constants.ProductionServer.baseURL.asURL()
var request = URLRequest(url: url.appendingPathComponent(path))
// HTTP Method
request.httpMethod = method.rawValue
// Common Headers
request.setValue(ContentType.json.rawValue, forHTTPHeaderField: HTTPHeaderField.acceptType.rawValue)
request.setValue(ContentType.json.rawValue, forHTTPHeaderField: HTTPHeaderField.contentType.rawValue)
// Parameters
switch self
case .login(let password):
request = try JSONParameterEncoder().encode(parameters, into: request) //where I got the error
return request
class APIClient
static func login(password: String, username: String, completion: @escaping (Result<UsersLogin, AFError>) -> Void)
AF.request(Router.login(username: username, password: password)).responseDecodable (response: DataResponse<UsersLogin, AFError>) in
completion(response.result)
LoginViewController
类(我替换了AF.request代码)
APIClient.login(password: password, username: username) result in
switch result
case .success(let user):
print(user)
case .failure(let error):
print(error.localizedDescription)
可编码 UsersLogin
模型
struct UsersLogin: Codable
let success: Bool
let username: String
let token: String?
enum CodingKeys: String, CodingKey
case success = "success"
case username = "username"
case token = "token"
你不能使用 Parameters
词典中带有 Encodable
类型的字典,作为 [String: Encodable]
不是 Encodable
,就像错误说的那样。我建议把这一步移到 asURLRequest
流程中的一个单独的函数,比如。
func encodeParameters(into request: inout URLRequest)
switch self
case let .login(parameters):
request = try JSONParameterEncoder().encode(parameters, into: request)
不幸的是,对于有很多路由的路由器来说,这并不能很好地扩展, 所以我通常把我的路由分解成小的枚举, 然后把我的参数移到单独的类型中, 再和路由器结合起来,从而产生 URLRequest
.
我花了点时间,但终于把它修好了。我也清理了一下代码。
enum Router: URLRequestConvertible
case login([String: String], String)
var baseURL: URL
return URL(string: "https://example.com")!
var method: HTTPMethod
switch self
case .login:
return .post
var path: String
switch self
case .login(_, let username):
return "/users/\(username)/login"
func asURLRequest() throws -> URLRequest
print(path)
let urlString = baseURL.appendingPathComponent(path).absoluteString.removingPercentEncoding!
let url = URL(string: urlString)
var request = URLRequest(url: url!)
request.method = method
switch self
case let .login(parameters, _):
request = try JSONParameterEncoder().encode(parameters, into: request)
return request
使用方法
let username = usernameTextField.text
AF.request(Router.login(["password": password], username)).responseDecodable(of: UsersLogin.self) (response) in
if let userLogin = response.value
switch userLogin.success
case true:
print("Successfully get token.")
case false:
print("Failed to get token with incorrect login info.")
else
print("Failed to get token.")
以上是关于如何使用Alamofire Router来组织API调用?(swift Alamofire5)的主要内容,如果未能解决你的问题,请参考以下文章
api请求失败时如何在swift alamofire中使用responsedecodable解析错误