c++ combine使用
In this article, we will learn how to architect and create an efficient and easy to use networking layer by leveraging Combine publishers, Codable, CustomStringConvertible protocol, and a custom Endpoint struct.
在本文中,我们将学习如何利用组合发布者,Codable,CustomStringConvertible协议和自定义Endpoint结构来设计和创建高效且易于使用的网络层。
At the end of the tutorial, you will have a ready-to-use implementation that you can easily copy and paste in your app and expand it the way you want.
在本教程的最后,您将获得一个易于使用的实现,可以轻松地将其复制并粘贴到您的应用中,并以所需的方式对其进行扩展。
The full source code is available at the bottom of the article.
完整的源代码位于文章底部。
开始吧 (Let’s Start)
Before we dive into the code, let’s first outline all components of our networking layer:
在深入研究代码之前,让我们首先概述网络层的所有组件:
Endpoint — a handy
struct
that haspath
andqueryItems
properties. By defining extensions on it, we can conveniently create a base URL of our REST APIs, define specific endpoints and headers (that will make more sense to you as we start implementing it, so don’t worry).端点 —具有
path
和queryItems
属性的便捷struct
。 通过在其上定义扩展,我们可以方便地创建REST API的基本URL,定义特定的端点和标头(在我们开始实现它时,对您来说更有意义,所以请不必担心)。Codable models — simple objects that can be created from JSON.
可编码模型 -可以从JSON创建的简单对象。
Network Controller — responsible for working directly with
URLSessionTask
s and decoding aCodable
model from the data. For example, it has a genericget()
method that returns a publisher containing a model.网络控制器 -负责直接使用
URLSessionTask
并从数据解码可Codable
模型。 例如,它具有通用的get()
方法,该方法返回包含模型的发布者。Logic Controller — abstracts the work being done by the network controller from the presentation layer (views/view controllers) and provides simple methods for querying models. For example, it may have a
getUsers()
method that calls the required method of a network controller and returns an array of users.逻辑控制器-从表示层(视图/视图控制器)抽象化网络控制器正在完成的工作,并提供查询模型的简单方法。 例如,它可能具有
getUsers()
方法,该方法调用网络控制器的必需方法并返回用户数组。
We are going to use a free REST API called Dummy API:
我们将使用称为Dummy API的免费REST API:
Now let’s start creating each component, one by one.
现在开始逐个创建每个组件。
可编码模型 (Codable Models)
We are going to fetch users from the Dummy API. The JSON looks like this:
我们将从Dummy API获取用户。 JSON如下所示:
So we create the following two structures:
因此,我们创建以下两个结构:
Note that we conform to the CustomStringConvertible protocol to easily debug our objects. We have the following handy extension that alleviates the burden to define the description
property for each conforming struct:
请注意,我们遵循CustomStringConvertible协议可以轻松调试对象。 我们具有以下方便的扩展,减轻了为每个符合结构定义description
属性的负担:
With models done, now let’s move to another component.
完成模型后,现在让我们转到另一个组件。
终点 (Endpoint)
Define an Endpoint
struct that we will extend to match specific API requirements:
定义我们将扩展以匹配特定API要求的Endpoint
结构:
Now, we need to create an extension in which we construct the URL
for the Dummy API and also define the headers
property containing an app ID (required by the Dummy API):
现在,我们需要创建一个扩展,在其中构建Dummy API的URL
,并定义包含应用程序ID(Dummy API所需)的headers
属性:
Now let’s define a few endpoints:
现在让我们定义一些端点:
We are going to use only the first one. I have provided the latter two to show how we can conveniently add parameters and set the path.
我们将只使用第一个。 我提供了后两者,以说明如何方便地添加参数和设置路径。
Now, it’s time for the NetworkController
.
现在,是时候使用NetworkController
。
网络控制器 (NetworkController)
First, let’s define a NetworkController
protocol:
首先,让我们定义一个NetworkController
协议:
As we can see, we have a method for querying a single Codable model.
如我们所见,我们有一种查询单个Codable模型的方法。
Now we need to create a concrete implementation of the protocol:
现在我们需要创建该协议的具体实现:
Note how in just four lines of code, we do the following:
请注意,仅用四行代码,我们如何执行以下操作:
Create and launch a
URLSessionDataTask
创建并启动
URLSessionDataTask
Obtain the
data
if no error occurred如果没有发生错误,则获取
data
- Decode a model object 解码模型对象
- Return a publisher containing either a model object or an error 返回包含模型对象或错误的发布者
We have the final component left — a LogicController
.
我们剩下的最后一个组件是LogicController
。
逻辑控制器 (LogicController)
Because we want to fetch users, our logic controller will be called the UsersLogicController
. First, let’s start with a protocol:
因为我们要获取用户,所以我们的逻辑控制器将被称为UsersLogicController
。 首先,让我们从一个协议开始:
We have the dependency on the NetworkController
and define three methods:
我们依赖于NetworkController
并定义了三种方法:
getUsers()
— queries 20 users by defaultgetUsers()
—默认情况下查询20个用户getUsers(count: Int)
— queries the specifiedcount
of usersgetUsers(count: Int)
-查询指定count
的用户getUser(id: String)
— queries one user matching the providedid
getUser(id: String)
—查询一个与提供的id
匹配的用户
The concrete implementation looks like this:
具体的实现如下所示:
As we can see, we work directly with endpoints and call the required methods of the NetworkController
. By marking the class as final
, we signal to other developers that this class is not designed to be subclassed.
如我们所见,我们直接使用端点并调用NetworkController
的必需方法。 通过将该类标记为final
,我们向其他开发人员发出信号,表明该类并非旨在被子类化。
Finally, we can test what we have created.
最后,我们可以测试我们创建的内容。
使用范例 (Usage Example)
Let’s initialize the NetworkController
and a UsersLogicController
:
让我们初始化NetworkController
和UsersLogicController
:
Create the subscriptions
property that will store our future subscription:
创建subscriptions
属性,该属性将存储我们将来的订阅:
Now we can fetch the users as follows:
现在,我们可以按以下方式获取用户:
As expected, we see User
objects pretty-printed as expected:
如预期的那样,我们看到User
对象打印出预期的样子:
结语 (Wrapping Up)
Check out this great video by John Sundell on managing URLs and endpoints, which inspired this post:
观看约翰·桑德尔(John Sundell)提供的有关管理URL和端点的精彩视频,该视频启发了这篇文章:
Want to learn more about Combine? Check out my other relevant pieces:
想更多地了解合并? 看看我其他相关的部分:
Thanks for reading!
谢谢阅读!
c++ combine使用