Frisbee
另一个用于 URLSession 的网络封装器。旨在简单、小巧并且易于在网络层为应用程序创建测试。
安装
Carthage
要将 Frisbee 集成到使用 Carthage 的 Xcode 项目中,请在 Cartfile 中指定它
github "ronanrodrigo/Frisbee" ~> 0.2.0
运行 carthage update 以构建框架,并将构建的 Frisbee.framework 拖到您的 Xcode 项目中。
CocoaPods
要将 Frisbee 集成到使用 CocoaPods 的 Xcode 项目中,请在 Podfile
中指定它
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '10.0'
use_frameworks!
target '<Your Target Name>' do
pod 'Frisbee', '0.2.0'
end
然后,运行以下命令
$ pod install
Swift 包管理器
要将 Frisbee 整合到您的 Swift 包管理器项目中,请设置 Package.swift
中的依赖项。
// swift-tools-version:4.0
import PackageDescription
let package = Package(
name: "<Your Packege Name>",
dependencies: [
.package(url: "https://github.com/ronanrodrigo/Frisbee.git", from: "0.2.0")
],
targets: [
.target(name: "<Your Packege Name>", dependencies: ["Frisbee"])
]
)
使用
GET 请求
可解码实体
Frisbee 发起的 Request
的响应将返回一个 Result<T>
的枚举。其中 T
必须是一个可解码实体。在这个指南中,将使用如下的 Movie
实体。
struct Movie: Decodable {
let name: String
}
发起请求
您可以将 Frisbee 的使用抽象到某个类中,并注入符合 Getable
协议的对象。因此,在生产代码中将使用 NetworkGet
对象的实例。
class MoviesController {
private let getRequest: Getable
// Expect something that conforms to Getable
init(getRequest: Getable) {
self.getRequest = getRequest
}
func listMovies() {
getRequest.get(url: someUrl) { moviesResult: Result<[Movie]> in
switch moviesResult {
case let .success(movies): print(movies[0].name)
case let .fail(error): print(error)
}
}
}
}
// Who will call the MoviesController must inject a NetworkGet instance
MoviesController(getRequest: NetworkGet())
查询参数
使用查询参数非常简单。只需创建一个 Encodable
结构体,并在 get(url:query:onComplete:)
方法中使用它。
struct MovieQuery: Encodable {
let page: Int
}
let query = MovieQuery(page: 10)
NetworkGet().get(url: url, query: query) { (result: Result<Movie>) in
// ...
}
POST 请求
与 GET 请求相同,Frisbee 有一个 Postable
协议。在生产就绪代码中,您将使用 NetworkPost
的实例。
发送请求
它的逻辑与 GET 请求相同。
class MoviesController {
private let postRequest: Postable
// Expect something that conforms to Postable
init(postRequest: Postable) {
self.postRequest = postRequest
}
func createMovie() {
postRequest.post(url: someUrl) { moviesResult: Result<[Movie]> in
switch moviesResult {
case let .success(movies): print(movies[0].name)
case let .fail(error): print(error)
}
}
}
}
请求体参数
使用请求体参数非常简单。只需创建一个 Encodable
结构体,并在 post(url:body:onComplete:)
方法中使用它。
struct MovieBody: Encodable {
let name: String
}
let body = MovieBody(name: "A New Movie")
NetworkPost().post(url: url, body: body) { (result: Result<Movie>) in
// ...
}
测试中的使用
在测试目标代码中,您可以创建自己的 Getable
(或根据需要为 Postable
)模拟。
public class MockGet: Getable {
var decodableMock: Decodable!
public func get<Entity: Decodable>(url: URL, completionHandler: @escaping (Result<Entity>) -> Void) {
get(url: url.absoluteString, completionHandler: completionHandler)
}
public func get<Entity: Decodable>(url: String, completionHandler: @escaping (Result<Entity>) -> Void) {
if let decodableMock = decodableMock as? Entity {
completionHandler(.success(decodableMock))
}
}
}
并且您将使用 MockGet
来测试 MoviesController
而不是使用 NetworkGet
。
class MoviesControllerTests: XCTestCase {
func testDidTouchAtListMoviesWhenHasMoviesThenPresentAllMovies() {
let mockGet = MockGet()
let movies = [Movie(name: "Star Wars")]
mockGet.decodableMock = movies
let controller = MoviesController(getRequest: mockGet)
controller.didTouchAtListMovies()
XCTAssertEqual(controller.moviesQuantity, movies.count)
}
}
Frisbee 的下一个功能
- GET 请求
- 创建 Carthage 发行版
- 创建 Cocoapod 发行版
- 查询参数构建器
- 问题 # 8 实现其他 HTTP 动词
- 问题 # 7 准备使用的模拟
- 问题 # 2 传递 Swift 错误
Telegram
为了协作、解决问题和了解 Frisbee 库的最新信息,请加入 Telegram 群组:https://t.me/FrisbeeLib