Netswift
是什么
这个库负责处理在 Swift 应用中创建可重用和可维护的网络层所需的重型工作。目前,它允许您以非常结构化和类型安全的方式轻易编写网络调用。它通过广泛使用关联类型和泛型类和结构体来实现。
为什么
Swift 中的网络可能从一开始就是一件繁杂的事情。为了快速入门,常常会忽略类型安全和可重用性。这正是 Netswift 突显其优势的地方!
在过去几年中,我的团队和我在执行网络请求时遇到了 spaghetti 代码和难以维护的代码库。由于 API 调用的特性,很难找到一个同时满足大多数需求、同时又灵活和未来的解决方案。
因此,为了提高我的 Swift 技能并摆脱困境,我自主研发了一个解决方案,以期缓解这些痛苦点。
本框架深受 John Sundell 和 Ray Wenderlich 撰写的博客文章的启发。我强烈推荐他们,如果您需要学习和提高编程技能的话!。
使用 Netswift
先决条件
我假设你已经构建了一个带有此 cocoapod 的 iOS 项目并准备好使用。如果没有,请按照安装步骤进行操作。
编写我们的第一次请求
像所有值得一读的教程一样,以下步骤将帮助您设置第一个Hello World请求。
我们将做什么
- 步骤 1:定义一个容器,该容器将作为我们的API实现的基类。
- 步骤 2:实现
NetswiftRoute
,定义端点的不同URLComponents
。 - 步骤 3:实现
NetswiftRequest
,定义如何将容器转换为URLRequest
。 - 步骤 4:传递一切给通用的
Netswift
类并发出第一个请求🙌 - 步骤 5: ????
- 步骤 6: 利润
👍
端点
为方便本教程,我已经为您设置了一个模拟API以供查询。它只有一个端点,返回一个包含标题的单个对象。 试试看
步骤 1
在这个特定的情况下,为了保持简单,我们可以定义一个新的 `enum
`。我们将使用它来实施所需的最小协议功能,这样我们就可以执行我们的请求。
所以继续吧;为您的项目添加一个新文件,命名方式由你决定。我选择了 `MyAPI
`。然后,别忘了导入 `Netswift
`,并像这样创建您的 API 容器
import Netswift
enum MyAPI {
case helloWorld
}
就这样了。现在,由于我们的 API 只有一个端点,实际上没有更多的事情要做。Swift 的 `enum
` 的好处是它们还可以有关联值。这在您需要将额外的数据传递到端点时非常有用,同时保持类型安全和结构化。很棒
步骤 2
所以我们有我们的 `enum
`。很好。但它并没有做什么。让我们来解决这个问题。
继续为它定义一个扩展,实现 `NetswiftRoute
协议
extension MyAPI: NetswiftRoute {
}
立即可见地,编译器开始抱怨。按'添加协议存根'会使其高兴起来。这将添加两个变量
host
:这定义了我们的 API 域名,通常是像www.example.com这样的东西。path
:我们的 API 上的特定资源。除非你只是 GET 网站的话,你将需要定义一个路径。
让我们继续实现这两个。
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` 案例)。当到了那个时刻,编译器将警告我们没有处理我们 `enum
` 的所有情况。
现在我们需要的就这些了。默认情况下,后台已经完成了大量工作;我们总是可以定义更多信息,例如方案(http 或 https),并且在需要时查询它,但在这个教程的上下文中,我们可以直接跳过!
步骤 3
现在我们已经设置了路由,所有我们需要的只是实现 `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>
。
太好了,现在我们差不多做完了!
第 4 步
现在是我们等待已久的时刻:发送我们的请求!
我们所需要做的就是实际执行我们的请求。要这样做,我们可以使用 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
请求!从这里,你可以进一步扩展并开始定义更复杂的要求。我还建议阅读文档,并覆盖默认实现,以便了解这个库真正可以达到什么效果
示例项目
要运行示例项目,请先克隆存储库,然后从 Example 目录运行 pod install
。它包含了上述教程的全部实现以及一些其他示例。
安装
Netswift 可以通过以下方式获取
- CocoaPods:要安装它,只需将以下行添加到您的 Podfile
pod 'Netswift'
- Swift 包管理器:要安装它,只需在 XCode 的集成包导航器中搜索它
作者
Dorian Grolaux,https://skwiggs.dev
许可证
Netswift 在 MIT 许可证下提供。有关更多信息,请参阅 LICENSE 文件。