Merchant是适用于iOS、iPadOS、macOS、watchOS和tvOS的一个类型安全的HTTP客户端。灵感来源于https://github.com/square/retrofit。
它允许您简单地“属性包装”任何可编码的Swift结构体,Merchant将负责发起HTTP请求并将HTTP响应数据解码到您的模型中,这一切都是在类型安全和声明性的方式下完成。
安装
CocoaPods
通过CocoaPods可以获取商家。要安装,只需在Podfile中添加以下行。
pod 'Merchant'
Swift包管理器
通过Swift包管理器可以获取商家。要安装,只需在Package.swift
文件中添加以下内容。
let package = Package(
...
dependencies: [
.package(url: "https://github.com/dubeboy/Merchant.git", from: "0.1.0")
],
...
)
使用方法
创建可解码模型
创建将表示您的API JSON响应的编码模型
struct Main: Codable { ... } // left out for brevity
struct WeatherData: Codable { ... } // left out for brevity
struct Weather: Codable {
let weather: [WeatherData]
let main: Main
}
在AppDelegate中初始化商家
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
let builder = Merchant.Builder()
.baseUrl("http://api.openweathermap.org/data/2.5")
.build()
Merchant(builder: builder)
return true
}
商家初始化自定义
要初始化商家,我们只需像上述代码片段中那样简单地设置baseUrl
即可,但商家有一些其他的初始化自定义选项
设置logger
向调试控制台输出的详细程度。可用选项包括:
.body
- 记录所有请求和API响应内容(默认)。.basic
- 仅记录请求方法和请求URL。.header
- 仅记录请求URL、请求头和响应头。.nothing
- 不记录任何内容。
例如,您可以像这样设置基本日志级别
builder.logger(.basic)
商家底层使用Alamofire,因此Merchant.Builder
允许您传入自定义的Alamofire Session
。
例如,您可以这样设置商家如何处理您的TLS安全
let manager = ServerTrustManager(evaluators: [url: PinnedCertificatesTrustEvaluator()])
let session = Session(serverTrustManager: manager)
builder.session(session)
您可以在这里了解有关自定义Alamofire会话对象的更多方式。
最后,您可以指定全局URL查询,例如API密钥等
builder.query(["api_key": "KEY_HERE"])
声明您的HTTP请求
以声明性方式创建您的HTTP API客户端@GET
、@POST
、PUT
、@DELETE
、@PATCH
或 @DELETE
属性包装器中,具体取决于要进行的HTTP请求。
包裹属性的类型的类型应该是一个可解码的结构体/类,它代表了特定的HTTP JSON响应。
例如,我们可以声明一个GET请求到以下URL http://api.openweathermap.org/data/2.5/weather,如下所示
struct ApplicationClient {
@GET(path = "/weather")
var getWeather: Weather
}
自定义请求
您可以为每个请求进行自定义,如添加头信息,formURLEncoding等,让我们更详细地看看
对于所有属性包装器,所有自定义参数都是可选的,因此您可以这样做
...
@GET
var getWeather: Weather
...
}
对于所有要求正文(如PUT
和POST
)的HTTP请求方法,您需要指定Encodable
正文模型。
您可以指定请求正文的可编码模型,如下所示
...
@POST(body: Main.self)
var postWeather: Weather // server returns the posted weather + its ID
...
您可以指定请求正文是否应该进行表单URL编码。false
为默认值,也可以指定随请求一起发送的头信息,如下所示
...
@POST(body: Main.self, formURLEncoded: true, headers: ["Content-Type": "application/json"])
var postWeather: Weather
...
您可以指定一个动态生成
的URL,该URL依赖于某些变量。
例如,假设您想指定一个删除任何用户的URL,给定其ID,您可以声明如下代码段,并在发出请求时实际注入user_id
的值。
...
@DELETE(path="/users/{user_id}")
var deleteUser: Bool
...
最后让我们发起请求。
创建一个上述声明的ApplicationClient
类的实例,并按如下方式调用所需的属性
class ViewController: UIViewController {
let client: ApplicationClient = ApplicationClient()
override func viewDidLoad() {
super.viewDidLoad()
getWeather(city: "Cape Town")
}
func getWeather(city: String) {
let query = ["q": city, "units": "metric"]
client.$getWeather(query: query) { [weak self] responseObject in
switch responseObject {
case .success(let response):
let weather: Weather = responseObject.body
...
case .failure(let error):
print(error.localizedDescription)
}
}
}
}
上述代码段将向http://api.openweathermap.org/data/2.5/weather?q=Cape%20Town&units=metric
发起一个GET
请求
调用站点自定义
以下提到的所有参数都是可选的,除了HTTP方法要求正文的正文参数。
对于如上所述的动态生成
的URL,您应该指定将所有URL占位符映射到相应值的path
字典,在这种情况下,我们将{user_id}
映射到56
如下所示
...
client.$deleteUser(path: ["user_id": "56"]) { _ in
...
}
...
上述代码段将生成URL /users/56
对于具有正文的请求,您还需要指定body
参数,以postWeather
上提到的示例为例,您可以发出如下请求
...
let main = Main(...)
client.$postWeather(body: main) { _ in
...
}
上述代码段将向http://api.openweathermap.org/data/2.5
发起一个包含JSON编码的Main
结构的POST
请求
作者
Divine Dube, [email protected] Twitter: @divinedube
许可证
商户可在MIT许可证下使用。更多信息请参阅LICENSE文件。