类型安全的网络调用变得简单
Netswift 提供了一种以结构化和类型安全的方式执行网络调用的简单方法。
从一开始,Swift 中的网络编程就可能很乏味。 为了加快速度,类型安全性和可重用性通常被忽视。 有一个包含所有 API 调用的巨大文件,变得难以维护吗? 这就是 Netswift 的用武之地。
使用 Netswift 执行网络调用非常简单
Netswift().peform(StripeAPI.Charges.get(byID: "1234")) { result in
switch result {
case .failure(let error):
// Our request failed: we can use the error to debug it
print(error)
case .success(let charge):
// Our request succeeded: we now have a Charge object from the Stripe API
print(charge.amount)
}
}
我假设您有一个已设置好的 iOS 项目,并且已经准备好使用此 cocoapod。 如果没有,请按照安装步骤。
与所有著名的教程一样,以下步骤将帮助您设置我们的第一个 Hello World 请求。
NetswiftRoute
,它定义了我们端点的不同 URLComponents
。NetswiftRequest
,它定义了如何将您的容器转换为 URLRequest
Netswift
类并执行您的第一个请求 🙌为了方便本教程,我提前为您设置了一个模拟 API 以供查询。 它只有一个端点,该端点返回一个包含标题的单个对象。 试试看
在这种特殊情况下,为了使事情简单起见,我们可以继续定义一个新的 enum
。 我们将使用它来实现所需的最低协议函数,这将使我们能够执行我们的请求。
所以继续; 向您的项目添加一个新文件,并随意命名。 我选择了 MyAPI
。 然后,不要忘记 import Netswift
,并创建您的 API 容器,如下所示
import Netswift
enum MyAPI {
case helloWorld
}
这几乎就是全部。 现在,由于我们的 API 只有一个端点,因此实际上没有更多内容。 Swift 的 enum
的优点在于它们也可以具有关联的值。 当您需要将其他数据传递到您的端点时,这非常方便,同时保持类型安全性和结构化。 漂亮👌
所以我们有了我们的枚举。 太棒了。 但它没有做太多事情。 让我们修复它。
继续并为其定义一个扩展,该扩展实现 NetswiftRoute
协议
extension MyAPI: NetswiftRoute {
}
立即,编译器开始抱怨。 按下“添加协议存根”会使其再次开心。 这将添加两个变量
host
:这定义了我们 API 的域名,通常类似于 www.example.com。path
:我们 API 上的特定资源。 除非您只是 GET-ing 一个网站,否则您需要定义一个路径。所以让我们继续并实现这两个。
var host: String {
return "my-json-server.typicode.com"
}
var path: String? {
switch self {
case .helloWorld: return "MrSkwiggs/Netswift-HelloWorld/Netswift"
}
}
我们刚刚做了什么?
我们的容器是一个 enum
,这意味着我们可以很容易地为每种情况定义不同的返回值。 对于 host
,我们总是想返回相同的值。
但是对于 path
,我们正在利用此功能。 我们以一种面向未来的方式进行设置,以便我们始终可以在以后添加路径(作为新的枚举情况)。 到那时,编译器会因为我们没有涵盖所有 enum
情况而对我们大喊大叫👍
这几乎就是我们现在需要的一切。 默认情况下,幕后完成了大量工作; 如果我们需要,我们总是可以定义更多信息,例如方案(http 或 https)和查询它,但在本教程的上下文中,我们可以直接跳过!
现在我们有了我们的路由设置,我们需要做的就是实现 NetswiftRequest
协议。 让我们在另一个扩展中做到这一点
extension MyAPI: NetswiftRequest {
}
这一次,我们不想让编译器立即为我们添加协议存根。 在此之前,让我解释一下我们需要提供给 Netswift
的其他信息;
Response
类型。 由于 Netswift 是通用的,因此它不知道我们想要从 API 端点获取哪种数据。 如果我们的请求定义了一个名为 Response
的类型,那么我们就准备好了。 最好的部分是,我们也可以使用 typealias
,它也可以正常工作👍所以现在,让我们只在我们的扩展中添加一个名为 Response
的内部类型
struct Response: Decodable {
let title: String
}
再次,我们刚刚写了什么?
好吧,首先,我们定义了一个类型,该类型模仿我们端点的响应结构。 也就是说,一个包含名为 title
的成员的对象,其类型为 String
。
然后,我们告诉编译器,我们的 Response
类型实现了 Decodable
协议。 Netswift
使用 Swift 的通用 JSONDecoder
。 默认实现都在幕后完成。
但是,编译器仍然不高兴。 现在是让它“添加协议存根”的好时机。 我们现在得到一个名为 serialise
的新函数。 这是我们在准备好之前需要定义的最后一部分。
那么让我们实现我们的 URLRequest
序列化吧?
func serialise(_ handler: @escaping NetswiftHandler<URLRequest>) {
handler(.success(URLRequest(url: self.url)))
}
好的,现在这是什么? 好吧,serialise
函数让 Netswift
获取一个可用的 URLRequest
,它可以发送出去。 但是,由于我们的实现非常基本,因此我们需要做的就是使用给定的 URL
实例化一个 URLRequest
。 但是等等。 self.url
来自哪里?
这个方便的计算变量来自 NetswiftRoute
协议。 它所做的只是简单地将您定义的所有 URLComponents 格式化为一个 String
,然后使用它来实例化并返回一个 URL
对象。
同样,那里有很多默认实现,但是您需要知道的是,对于我们当前的 .helloWorld
情况,self.url
将使用 <scheme><host>/<path><query>
。
太棒了,我们现在几乎完成了!
现在是我们一直在等待的时刻:发送我们的请求!
我们需要做的就是实际执行我们的请求。 为此,我们可以使用默认 Netswift
类的实例。 我们只需要调用这个
Netswift().perform(MyAPI.helloWorld) { result in
switch result {
case .failure(let error):
// Our request failed: we can use the error to debug it
print(error)
case .success(let value):
// Our request succeeded: we now have an object of type MyAPI.Response available to use
print(value.title)
}
}
这就是我们使用 Netswift
完成的第一个请求! 从这里开始,您可以更进一步,开始定义更复杂的请求。 我还建议阅读文档并覆盖默认实现,以了解该库真正可以实现的功能👌
要运行示例项目,请克隆 repo,并首先从 Example 目录运行 pod install
。 它包含上面教程的完整实现,以及一些其他示例。
Netswift 可通过以下方式获得
pod 'Netswift'
Dorian Grolaux, https://skwiggs.dev
Netswift 在 MIT 许可证下可用。 有关更多信息,请参见 LICENSE 文件。