KiNetworking 1.3.0

KiNetworking 1.3.0

Kishimotovn 维护。



 
依赖项
Alamofire>= 0
PromisesSwift>= 0
SwiftyJSON>= 0
 

  • 作者
  • Anh Phan Tran

KiNetworking

[![CI 状态](https://img.shields.io/travis/Anh Phan Tran/KiNetworking.svg?style=flat)](https://travis-ci.org/Anh Phan Tran/KiNetworking) Version License Platform

这个库是一个为高配置 + TDD 构建的现代网络层。库利用 Alamofire、Promises 和 SwiftyJSON 的特性,帮助您直接从 API 调用到模型转换。

示例

要运行示例项目,克隆仓库,然后首先从 Example 目录中运行 pod install

需求

安装

通过 CocoaPods 可以获取 KiNetworking。安装它,只需将以下行添加到您的 Podfile 文件中

pod 'KiNetworking'

用法

要发出请求,首先需要提供请求运行的 API 服务。这样,您可以为应用在的每个环境获取一个服务实例。

API 服务需要 APIServiceConfiguration 来初始化

let config = APIServiceConfig(
  name: "Staging",
  base: "https://stagingBaseURL",
  commonHeaders: [
    "Someheaderkey": "SomeValue"
  ])
config?.debugEnabled = .request // .none, .request, .response
let service = APIService.init(config!)

获取服务后,您可以创建一个请求并在服务上执行,如下所示

let request = Request(method: .get, endpoint: "someEndpoint")
request.execute(on: service).then(...).catch(...)

服务将调用请求(请求协议)并返回响应(响应协议)。

请求和请求协议

请求协议有以下参数

public protocol RequestProtocol {
  // Endpoint of the request
  var endpoint: String { get }
  
  // Request's params that will be encoded into the final request URL
  var parameters: Parameters? { get }
  
  // Request specific headers, will override service's header if share the same key, else, append to the service's headers
  var additionalHeaders: HeadersDict? { get set }
  
  // Method: .get, .post, .put, .patch, .delete
  var method: Alamofire.HTTPMethod { get }

  // Request specific cache policy, if nil will use the service's cache policy
  var cachePolicy: URLRequest.CachePolicy? { get }
  
  // Request specific timeout, if nil will use the service's timeout interval
  var timeout: TimeInterval? { get }
  
  // Queue that we make the request, if nil will use the service's context
  var context: DispatchQueue? { get }
  
  // Body of the request: .json, .formURL, .custom, .data
  var body: RequestBody? { get set }

  func headers(in service: APIServiceProtocol) -> HeadersDict
  func fullURL(in service: APIServiceProtocol) throws -> URL
  func urlRequest(in service: APIServiceProtocol) throws -> URLRequest
}

实现了这个协议的名为 Request 的基类

响应和响应协议

响应协议有以下参数

public protocol ResponseProtocol {
  /// Type of response (success or failure)
  var result: Response.Result { get }

  /// Encapsulates the metrics for a session task.
  /// It contains the taskInterval and redirectCount, as well as metrics for each request / response
  /// transaction made during the execution of the task.
  var metrics: ResponseTimeline? { get }

  /// Request
  var request: RequestProtocol { get }

  /// Return the http url response
  var httpResponse: HTTPURLResponse? { get }

  /// Return HTTP status code of the response
  var httpStatusCode: Int? { get }

  /// Return the raw Data instance response of the request
  var data: Data? { get }

  /// Attempt to decode Data received from server and return a JSON object.
  /// If it fails it will return an empty JSON object.
  /// Value is stored internally so subsequent calls return cached value.
  ///
  /// - Returns: JSON
  func toJSON() -> JSON

  /// Attempt to decode Data received from server and return a String object.
  /// If it fails it return `nil`.
  /// Call is not cached but evaluated at each call.
  /// If no encoding is specified, `utf8` is used instead.
  ///
  /// - Parameter encoding: encoding of the data
  /// - Returns: String or `nil` if failed
  func toString(_ encoding: String.Encoding?) -> String?
}

实现了这个协议的名为 Response 的基类

操作

这个库原始就提供了 DataOperation 和 JSONOperation。

DataOperation 只是直接返回用于您操作的数据响应的操作。

另一方面,DecodableOperation 或 JSONOperation 可以帮助您直接从请求中返回模型。

// Customer class with Decodable

struct Customer: Decodable {
}
class GetCustomerRecord: DecodableOperation<Customer> {
  public init(customerId: Int) {
    super.init()
    self.request = SampleJWTRequest(method: .get, endpoint: "/users/\(customerId)", parameters: nil, encoder: JSONEncoding.default)
    self.request.timeout = 15
  }
}
// Customer class with JSON

class Customer {
  init?(from json: JSON) {
    // Do your init here
  }
}
class GetCustomerRecord: JSONOperation<Customer> {
  public init(customerId: Int) {
    super.init()
    self.request = SampleJWTRequest(method: .get, endpoint: "/users/\(customerId)", parameters: nil, encoder: JSONEncoding.default)
    self.request.timeout = 15
    self.onParseResponse = { json in
      return Customer(from: json)
    }
  }
}
// When you need to invoke the get customer record API:

...
let service = APIService(...)
GetCustomerRecord(customerId: 123).execute(on: service).then { customer in
  // Do what you want with customer
}.catch { error in
  // Show error
}

APIServiceDelegate

每个API服务可以选择一个代理,如果需要的话

public protocol APIServiceDelegate: class {
func service(_ apiService: APIServiceProtocol, willExecute request: RequestProtocol)
func service(_ apiService: APIServiceProtocol, shouldHandleCode errorCode: Int, on request: RequestProtocol) -> Bool
func service(_ apiService: APIServiceProtocol, handleResponse: ResponseProtocol, on request: RequestProtocol) -> Promise<ResponseProtocol>
}

此代理可以用以授权或刷新请求的访问令牌。

Author

Anh Phan Tran, [email protected]

License

KitNetworking 适用于MIT许可证。有关更多信息,请参阅LICENSE文件。