这是一个用于简化网络层的微型架构库。该库的主要目标是为网络层提供一个简单的抽象,同时保持易用性和可测试性。
这个库不提供任何自定义的 API 调用实现,你必须使用你自己的实现,或者使用像 Alamofire 这样的库。
这个库有三个主要的协议。
这个协议用于获取完整的 URL 和请求的 HTTPMethod。默认情况下,使用全局配置中设置的 URL。
你必须首先设置全局 URL
NetworkConfiguration.setCurrentURL(URL(string:"https://www.myApi.com")!)
实现 Router 协议
enum UserRouter: Router {
case user(id: String)
var route: Route {
switch self {
case .user(let id):
return Route(path: "user\(id)", method: .get)
}
}
}
如果你不想使用全局 URL,你可以通过实现 baseURL
属性来更改。
enum UserRouter: Router {
case user(id: String)
var route: Route {
switch self {
case .user(let id):
return Route(path: "user/\(id)", method: .get)
}
}
var baseURL: URL {
return URL(string:"https://www.anotherapi.com")
}
}
建议不要使用一个枚举来处理所有可能的路径,最好每个域使用一个。例如,如果你有 user
和 packages
路由,你可以创建两个枚举,一个用于用户路由,另一个用于包路由。
这个带有关联类型的协议用于抽象 Request 的配置。它有三个关键参数:
你希望回调响应所在的队列。
保存一个函数的属性,该函数将数据解析为关联的类型。
类型为 RequestFactory
的属性,这是一个用 Router
实现和一个接受 URLRequest 并返回另一个 URLRequest 的函数初始化的结构体。 这个函数的目的是创建组合,允许你为 URLRequest 添加任何你想要的配置。
该库为此协议提供了一个默认实现
public struct RequestType<Response>: Request {
public let responseQueue: DispatchQueue
public let requestParser: RequestParser<Response>
public let requestFactory: RequestFactory
public init(responseQueue: DispatchQueue = .global(qos: .default),
requestFactory: RequestFactory,
requestParser: @escaping RequestParser<Response>) {
self.responseQueue = responseQueue
self.requestParser = requestParser
self.requestFactory = requestFactory
}
}
当响应类型为 Decodable 时,它有自己的自定义扩展
extension RequestType where Response: Decodable {
init(responseQueue: DispatchQueue = .global(qos: .default),
requestFactory: RequestFactory,
decoder: JSONDecoder = JSONDecoder()) {
self.init(responseQueue: responseQueue, requestFactory: requestFactory) {
return try decoder.decode(Response.self, from: $0)
}
}
}
以及当响应为 Void 时
extension RequestType where Response == Void {
init(responseQueue: DispatchQueue = .global(qos: .default),
requestFactory: RequestFactory) {
self.init(responseQueue: responseQueue, requestFactory: requestFactory) {
return ()
}
}
}
大多数时候,你将使用此实现来构建你的 Request,但是如果你需要覆盖一些边缘情况,你可以实现该协议并应用你的自定义配置。
该库提供了一个自由函数 compose
,它接受一个类型为 RequestBuilder
的可变参数,这只是签名 (URLRequest) -> URLRequest
的类型别名。此函数接受 N 个满足签名的函数,并减少它们,直到获得一个 URLRequest
。此函数返回一个 RequestBuilder
。
例子
let requestBuilder = compose(addURLParams(["years": "2015"]), addHeaders(["Authorization":"Bearer...."]))
RequestFactory(router: UserRouter.user(id: "12"), requestBuilder: requestBuilder)
此外,该库还提供了一个自由函数,用于使用 WritableKeyPaths 的优点来改变 URLRequest
set(to: \.cachePolicy, .reloadIgnoringCacheData)
这与 compose
完全兼容,这意味着你可以这样做
compose(set(to: \.cachePolicy, .reloadIgnoringCacheData), set(to: \.networkServiceType, .background))
此协议用于抽象网络客户端,只有一个函数接受一个 Request
和一个闭包作为回调的响应(此闭包具有类型别名 Response<T>
并将 Result
类型作为参数)。
使用 Alamofire 的例子
public func execute<T: Request>(_ request: T, response: @escaping Response<T.Response>) {
let urlRequest = request.urlRequest
Alamofire.request(urlRequest)
.responseData(queue: request.responseQueue) {
switch $0.result {
case .success(let data):
do {
response(.success(try request.parser(data)))
} catch {
response(.failure(error))
}
case .failure(let error):
response(.failure(error))
}
}
}
}
只需将以下行添加到 podfile 中
pod `JustNetworking`, `~> 2.0`
JustNetworking 在 MIT 许可证下发布。有关详细信息,请参见 LICENSE。