RxRetroSwift 3.0.1

RxRetroSwift 3.0.1

Michael Henry Pantaleonx 维护。



 
依赖
RxSwift~> 5.0
RxCocoa~> 5.0
 

RxRetroSwift

CI Status Version License Platform

它有什么功能?

它简化了您的 RESTful API 调用,自动将 HttpResponse 转换为指定的模型,以及使用苹果公司新的 Codable 功能处理错误。

例如,在一个获取特定用户信息的请求中,您有一个 User 模型,您只需使 User 模型符合 Codable,并在使用 RequestCaller 时指定它。

{
  "name":"kel",
  "email":"[email protected]"
}

符合 Codable 的 User 模型。

struct User: Codable {
  var name:String
  var email:String
}

这将会自动将响应转换为 User 实例模型。

示例

let caller = RequestCaller(config: URLSessionConfiguration.default)

func fetchUser(byUserId userId) -> Observable<Result<User, ErrorModel>> {
    let request:URLRequest = RequestModel(
      httpMethod: .get,
      path: "v1/users/\(userId)")
      .asURLRequest()
    return caller.call(request)
  }

假设它是一个用户数组的示例;由于 Array 符合 Codable,您只需指定类型为 [User]

示例

func fetchUsers() -> Observable<Result<[User], ErrorModel>> {
    let request:URLRequest = RequestModel(
      httpMethod: .get,
      path: "v1/users")
      .asURLRequest()
    return caller.call(request)
  }

关于处理响应错误

RxRetroSwift 提供了一个 typealias ErrorCodable,它是 HasErrorInfoDecodable 协议的组合

public typealias DecodableError = Decodable & HasErrorInfo

例如,您的登录请求的 JSON 错误响应是

{
  "message": "Unable to login."
  "details": {
    "password": "You changed your password 2 months ago."
  }
}

并且您的模型是

struct ErrorModel {

  var errorCode:Int?
  var message:String
  var details:[String:String]
}

如何处理不期望返回对象或模型的请求?

RxRetroSwift 提供了一个方法,它将返回 Observable>。

public func call<DecodableErrorModel:DecodableError>(_ request: URLRequest)
  -> Observable<Result<RawResponse, DecodableErrorModel>>
public struct RawResponse {
  
  public var statusCode:Int
  public var data:Data?
  
  init(statusCode:Int, data:Data?) {
    self.statusCode = statusCode
    self.data       = data
  }
}

示例

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

需求

功能

  • 易于使用且简单,只需几行代码(不包括 RxSwift)。
  • 干净整洁的实现。
  • 灵活的错误处理。
  • 简化您的REST API客户端。

待办事项

  • 单元测试和集成测试(完成)
  • 添加示例(完成)
  • 支持您 URLRequest 的不同身份验证方法。

安装

CocoaPods

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

pod 'RxRetroSwift'

Swift 包管理器

.package(url: "https://github.com/michaelhenry/RxRetroSwift", from: "2.1"),

示例实现

使用JSONPlaceholder API。您还可以查看示例项目

class APIClient {
 
  static var shared = APIClient()
  var caller = RequestCaller.shared
  
  private init() {
    
    RequestModel.defaults.baseUrl = "https://jsonplaceholder.typicode.com"
  }
  
  func fetchPosts() -> Observable<Result<[Post], ErrorModel>> {
    let request = RequestModel(
      httpMethod: .get,
      path: "posts")
      .asURLRequest()
    
    return caller.call(request)
  }
  
  func insertPost(post:Post) -> Observable<Result<Post, ErrorModel>> {
    let request = RequestModel(
      httpMethod: .post,
      path: "posts",
      payload: post.dictionaryValue)
      .asURLRequest()
    
    return caller.call(request)
  }

  func fetchComments() -> Observable<Result<[Comment], ErrorModel>> {
    let request = RequestModel(
      httpMethod: .get,
      path: "comments")
      .asURLRequest()
    
    return caller.call(request)
  }
  
  func fetchAlbums() -> Observable<Result<[Album], ErrorModel>> {
    let request = RequestModel(
      httpMethod: .get,
      path: "albums")
      .asURLRequest()
    
    return caller.call(request)
  }
  
  func fetchPhotos() -> Observable<Result<[Photo], ErrorModel>> {
    let request = RequestModel(
      httpMethod: .get,
      path: "photos")
      .asURLRequest()
    
    return caller.call(request)
  }
  
  func fetchTodos() -> Observable<Result<[Todo], ErrorModel>> {
    let request = RequestModel(
      httpMethod: .get,
      path: "todos")
      .asURLRequest()
    
    return caller.call(request)
  }
  
  func fetchUsers() -> Observable<Result<[User],ErrorModel>> {
    
    let request = RequestModel(
      httpMethod: .get,
      path: "users")
      .asURLRequest()

    return caller.call(request)
  }
}

测试

class TestAPIClient:QuickSpec {
  
  override func spec() {
    
    describe("Using JSONPlaceholder API") {
      
      let apiClient = APIClient.shared
      
      it("Check Posts result count"){
        let observable = apiClient.fetchPosts()
        expect(observable.map { $0.value!.count }).first == 100
      }
      
      it("Can insert post"){
        var post = Post()
        let title = "This is my post"
        let userId = 101
        let body = "This is a message body"
        
        post.title = title
        post.userId = userId
        post.body = body
        let observable = apiClient.insertPost(post: post)
        expect(observable.map { $0.value?.title ?? "" }).first == title
        expect(observable.map { $0.value?.userId ?? 0 }).first == userId
        expect(observable.map { $0.value?.body ?? "" }).first == body
      }
      
      it("Check Comments result count"){
        let observable = apiClient.fetchComments()
        expect(observable.map { $0.value!.count }).first == 500
      }
      
      it("Check Albums result count"){
        let observable = apiClient.fetchAlbums()
        expect(observable.map { $0.value!.count }).first == 100
      }
      
      it("Check Photos result count"){
        let observable = apiClient.fetchPhotos()
        expect(observable.map { $0.value!.count }).first == 5000
      }
      
      it("Check Todos result count"){
        let observable = apiClient.fetchTodos()
        expect(observable.map { $0.value!.count }).first == 200
      }
      
      it("Check Users result count"){
        let observable = apiClient.fetchUsers()
        expect(observable.map { $0.value!.count }).first == 10
      }
    }
  }
}

贡献

请随意提交拉取请求或提出任何有用的建议。

作者

Michael Henry Pantaleon, [email protected]

许可协议

RxRetroSwift 在MIT许可下可用。更多信息请查看LICENSE文件。