swift调用api接口_使用OperationQueue在Swift中链接API调用

swift调用api接口

Let us make an API call, followed by another. Wouldn’t that be nice?

让我们进行一个API调用,然后再进行另一个。 那不是很好吗?

Difficulty: Beginner | Easy | Normal | ChallengingThis article has been developed using Xcode 11.5, and Swift 5.2.4

难度:初学者| 容易| 普通 | 具有挑战性本文是使用Xcode 11.5和Swift 5.2.4开发的

先决条件: (Prerequisites:)

为什么需要链接API调用? (Why would you need to chain API calls?)

这个例子 (The example)

So here is the deal. I want to download the list of users from an API provided by regres.in . Once we have that, we want to download the full data from that user.

所以这里是交易。 我想从regres.in提供的API下载用户列表。 有了这些信息后,我们想从该用户那里下载全部数据。

When we use regres.in we will have to hit the following API endpoints:

当我们使用regres.in时,我们必须命中以下API端点:

  • /api/users

    / api /用户
  • /api/users/#

    / api / users /#

and in between the two? We are going to need to decode the JSON String.

在两者之间? 我们将需要解码JSON String

Each of these Operations need to be complete before the preceding one. In order to do so we are going to need a great tutorial. That tutorial? That is the one you're reading!

这些Operation的每一个都需要在上一个Operation之前完成。 为此,我们将需要一个出色的教程。 那本教程? 那就是你正在读的那个!

什么是代码,什么不是 (What the code is, and what it isn’t)

This isn’t a theoretical discussion of Operation and OperationQueue, and is a practical example of both. It does include tests, however I'm not going to claim that the testing is perfect (it's up to 78% code coverage so it's not awful but does give an indication of how testing can take place). The architecture of this project...this isn't an article about architecture and I usually use MVVM myself but here we just whack the result in the view controller (come at me!). Error handling has begin, but the Error where there is one isn't passed to the the view controller and isn't handled. The testing does cover errors though (partially).

这不是OperationOperationQueue的理论讨论,而是两者的实际示例。 它的确包含测试,但是我不会断言该测试是完美的(它的代码覆盖率高达78%,因此虽然不算糟糕,但确实说明了如何进行测试)。 该项目的架构...这不是一篇有关架构的文章,我通常自己使用MVVM,但在这里我们只是将结果打包到视图控制器中(请来找我!)。 错误处理已经开始,但是没有Error不会传递给视图控制器,也不会被处理。 测试确实(部分)涵盖了错误。

I’d recommend that you look through the code repo as you read — it’s right here for download

我建议您在阅读时仔细阅读代码存储库-可以在此处下载

代码依赖 (Code Dependencies)

In order to download, we are going to use urlsession. Now luckily I've already developed a nice HTTP Manager class, which I'll drag and drop into the project.

为了下载,我们将使用urlsession 。 现在幸运的是,我已经开发了一个不错的HTTP Manager类 ,将其拖放到项目中。

等一下 这是什么样子? (Wait, what? What’s this going to look like?)

They’ll be a couple of buttons on a viewcontroller that performs the two following actions:

它们将是执行以下两个操作的视图控制器上的几个按钮:

  • Download a list of users (Operation 1), and then decode it (Operation 2)

    下载用户列表(操作1),然后对其进行解码(操作2)
  • Download a list of users (Operation 1), and then decode it (Operation 2), and then download a specific user (Operation 3) and then decode the eventual user

    下载用户列表(操作1),然后对其进行解码(操作2),然后下载特定用户(操作3),然后解码最终用户

The eventual result is then displayed on a textview.

然后将最终结果显示在textview上。

Image for post

操作课 (Operation class)

高层描述 (The high-level description)

Operation provides us with ways to perform operations concurrency in association with OperationQueue, built on top of GCD - and since Operation allows us to add dependency among operations (and even cancel or suspend them) it is a perfect example for our little project without needing to delve into the detail of threading or your device cores. Excellent.

Operation为我们提供了与基于GCD的 OperationQueue关联的执行操作并发的方法-由于Operation允许我们在操作之间添加依赖项(甚至取消或暂停它们),因此这是我们的小项目的完美示例,而无需执行深入研究线程或设备核心的细节。 优秀的。

所以… (So…)

QueueManager

队列管理器

This is a queue that controls the order of execution of the operations contained within the queue (this is actually a priority queue ). An OperationQueue attempts to execute as many operations in parallel as the host device can support.

这是一个队列,用于控制队列中所包含操作的执行顺序(实际上是优先级队列 )。 OperationQueue尝试并行执行主机设备可以支持的尽可能多的操作。

In order to manage that there is a QueueManager that allows any number of Operation to be added to the queue. To ensure that we always add to the same queue the QueueManager will be a Singleton instance.

为了管理,有一个QueueManager允许将任意数量的Operation添加到队列中。 为了确保我们总是将相同队列添加到队列中, QueueManager将是一个Singleton实例。

Image for post
Click for Gist 单击要点

Now the tests for QueueManager probably go further than they should do, as they start to test the functions of OperationQueue (so not my finest hour) but are visible through the repo code if you download it, and take a look.

现在,对QueueManager的测试可能会超出其应做的范围,因为它们开始测试OperationQueue的功能(因此不是我最好的时间),但是如果您下载了repo代码,就可以看到它,并进行查看。

Operation (Operation)

Operation is an abstract class that is subclassed in order to perform specific tasks. A given Operation usually runs on a different thread from the one that created it.

Operation是为执行特定任务而被子类化的抽象类。 给定的Operation通常在与创建它的线程不同的线程上运行。

UserListDecodeOperation

UserListDecodeOperation

First we will cover decoding a JSON String. This UserListDecodeOperation is subclassed from Operation. The main() function is where the decoding will take place, but we set a property with an Error that can be passed through the different Operation objects so that these can be dealt with at an appropriate point.

首先,我们将介绍解码JSON字符串。 此UserListDecodeOperationOperation子类。 main()函数是进行解码的地方,但是我们为Error设置了一个属性,该属性可以通过不同的Operation对象传递,以便可以在适当的时候进行处理。

Image for post
Click for Gist 单击要点

The content is passed back through the completion handler (using typealias)

内容通过完成处理程序传回(使用typealias )

yet the data used is passed through the dataFetched property which is populated after the Retrieval operation is made.

但是使用的数据通过dataFetched属性传递,该属性在执行Retrieval操作后填充。

The other property, decodedURL is the URL that will be fetched when we choose the retrieve the individual user.

另一个属性decodedURL是当我们选择检索单个用户时将获取的URL。

UserListRetrievalOperation

UserListRetrievalOperation

Operations can either be Concurrent or Non-concurrent, and there is an important distinction. The network call is a Concurrent async operation, meaning that Operation does not automatically know when it is complete (like in UserListDecodeOperation above). The solution to this is to create a base class that will call finish() when the Operation is complete (or when the Operation is cancelled.

操作可以是ConcurrentNon-concurrent ,并且有一个重要的区别。 网络调用是一个并发异步操作,这意味着该Operation不会自动知道它何时完成(例如上面的UserListDecodeOperation)。 解决方案是创建一个基类,该基类将在Operation完成时(或取消Operationfinish()调用finish()

Image for post
Click for Gist 单击要点

So our UserListRetrievalOperation class subclasses NetworkOperation, and then the OperationQueue will behave properly when the network request is made!

因此,我们的UserListRetrievalOperation类将NetworkOperation子类化,然后在发出网络请求时OperationQueue将正常运行!

Image for post
Click for Gist 单击要点

This does of course call my HTTP Manager and return the data (or an error). The dataFetched is populated which can then be used by the UserListDecodeOperation. To do this...use the DataManager (shown below).

当然,这确实会调用我的HTTP管理器并返回数据(或错误)。 填充dataFetched,然后可由UserListDecodeOperation 。 为此,请使用DataManager (如下所示)。

I’ve also created similar UserRetrievalOperation and UserDecodeOperation which are in the Repo for clarity (as they are similar to the classes described here) and aren’t rolled into a generic class to make this a little easier to understand (I hope). The tests are in the Repo too!

为了清楚起见,我还在回购中创建了类似的UserRetrievalOperationUserDecodeOperation (因为它们与此处描述的类相似),并且没有加入通用类以使其更容易理解(我希望)。 测试也在回购中

调度作业 (Scheduling operations)

高层描述 (The high-level description)

The DataManager is responsible for scheduling operations, and is defined below.

DataManager负责调度操作,定义如下。

数据管理器 (DataManager)

The DataManager is going to be a class that is responsible for scheduling these Operation objects.

DataManager将成为负责调度这些Operation对象的类。

Let us look at the DataManager with the function retrieveUserList that retrieves the UserList, and then decodes it.

让我们看一下带有retrieveUserList然后对其解码的函数retrieveUserListDataManager

Image for post
Click for Gist 单击要点

The initializer allows us to connect to any QueueManager instance (this would be a good opportunity to look at any QueueManager conforming to a Protocol in order to use Dependency Injection using Protocols

初始化程序使我们可以连接到任何QueueManager实例(这是查看符合协议的任何QueueManager的好机会,以便使用通过协议进行 依赖注入

Diving into the retrieveList function we can see that there are two operation objects, fetch and parse that do (pretty much) what we would expect.

深入到retrieveList函数中,我们可以看到有两个operation对象,即fetchparse ,它们执行(几乎)我们期望的操作。

Now the real issue is how do we pass the data from the fetch Operation to the parse operation?

现在真正的问题是如何将数据从fetch Operation传递到parse operation

This is where an adaptor comes into use.

这是使用适配器的地方。

Image for post
Click for Gist 单击要点

This links the properties for dataFetched and error, using BlockOperation (which is handy as it means the Operationinstance does not have to be subclassed. They are unowned since the references will never become nil (so will never cause a disturbing runtime crash).

这将使用BlockOperation链接dataFetchederror的属性(这很方便,因为它意味着不必对Operation实例进行子类化。由于引用将永远不会为nil(因此永远不会造成令人不安的运行时崩溃),因此它们是unowned BlockOperation

Also of note is the idea of Dependencies — the adapter has a dependency of fetch, and the parse has a dependency of the adapter. How?

还需要注意的是“ 依赖关系”的概念-适配器具有fetch的依赖关系,而parse具有adapter的依赖关系。 怎么样?

adapter.addDependency(fetch) parse.addDependency(adapter)

adapter.addDependency(fetch) parse.addDependency(adapter)

which can then be added to the QueueManager instances operation queue through queueManager.addOperations([fetch, parse, adapter]).

然后可以通过queueManager.addOperations([fetch, parse, adapter])将其添加到QueueManager实例操作队列中。

The data is returned to the caller through a completionHandler, that is awesome (probably).

数据通过完成处理程序返回到调用方,这很棒(可能)。

改进之处 (Improvements)

This code isn’t production ready but is indicative of what can be achieved using Operation and OperationQueue and how such an implementation might be tested.

该代码尚未投入生产,但表明使用OperationOperationQueue可以实现什么,以及如何测试这种实现。

There are obvious improvements — why have UserDecodeOperation and UserListDecodeOperation when one class could decode both? The answer is this is a minimal example, and has been written for this guide - it is not production-ready in any way.

有明显的改进-当一个类可以同时解码UserDecodeOperationUserListDecodeOperation时,为什么要使用UserDecodeOperationUserListDecodeOperation ? 答案是,这是一个最小的示例,并且已为该指南编写-它不以任何方式准备就绪。

Equally there is a QueueManagerMock class that is just a QueueManager. This is true, and it's there so I can choose to improve this guide in the future (did you know I update these guides?), although this might be a good opportunity to use Dependency Injection).

同样有一个QueueManagerMock类,它只是一个QueueManager 。 的确如此,并且确实存在,因此我可以选择将来对本指南进行改进(您知道我是否更新了这些指南吗?),尽管这可能是使用Dependency Injection的好机会。

The way that URLs have been built, frankly makes me feel sick. It’s written like this for speed, rather than using my own method of building urls in Swift.

坦率地说,URL的构建方式使我感到恶心。 这样写是为了提高速度,而不是使用我自己的在Swift构建url的方法。

Download the code: It’s right HERE

下载代码:在 这里 正确

结论 (Conclusion)

This is quite an article. Moving to using OperationQueue and Operation rather than closures to chain API calls has been a challenge of subclassing and understanding exactly what is happening under the hood for these classes.

这是一篇相当不错的文章。 转向使用OperationQueueOperation而不是使用闭包来链接API调用一直是子类化和准确了解这些类的幕后工作的挑战。

Worth it?

值得?

Well you have the option of having control over these operation objects, and that means you can cancel subsequent API calls if a previous one fails. This can be done from within the operation (see that I’ve done this in UserDecodeOperation in the Repo but can also be done from outside the class — providing great flexibility.

好吧,您可以选择控制这些operation对象,这意味着如果前一个API失败,则可以取消后续的API调用。 这可以从操作内部完成(请参见我在Repo的 UserDecodeOperation中完成了此UserDecodeOperation ,但也可以从类外部完成–提供了极大的灵活性。

As ever, the developer needs to decide the approach using the tools at their disposal. I hope that this article has helped you add these tools into your tool kit.

与以往一样,开发人员需要使用可供使用的工具来决定方法。 我希望本文能帮助您将这些工具添加到工具箱中。

If you’ve any questions, comments or suggestions please hit me up on Twitter

如果您有任何疑问,意见或建议,请在Twitter上打我

翻译自: https://medium.com/@stevenpcurtis.sc/use-operationqueue-to-chain-api-calls-in-swift-71eefd6891ef

swift调用api接口

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Ceph是一个可靠的、数据自动重均衡、自动恢复的SDS(软件定义存储)分布式存储系统,功能主要有三大块:块存储、对象存储、文件系统。Ceph不但是提供了统一存储,并且同时还充分利用了客户端的计算能力,在存储每一个数据时,都会通过计算得出该数据存储的位置,尽量将数据分布均衡,同时由于Ceph的设计,采用了CRUSH算法、HASH环等方法,使得它不存在传统的单点故障的问题,且随着规模的扩大性能并不会受到影响。不管是私有云还是公有云,随着云架构的发展,Ceph 成为了OpenStack、Proxmox标配的后端存储,不光如此,就连目前最火的容器编排 Kubernetes 持久存储也都支持 Ceph ,让 Ceph 成为当前主流的存储系统,而对 Ceph 存储的学习也就变的刻不容缓。 该课程属于比较基础的 Ceph 存储课程,旨在让大家能快速上手对 Ceph 集群的部署以及操作,主要讲解以下几个方面: 1.     架构的介绍2.     集群的多种部署方式3.     块存储部署,客户端使用及快照、克隆和镜像4.     对象存储的部署及简单使用5.     Ceph FS 文件系统的部署、客户端使用及导出为NFS6.     集群的操作和管理,包括服务,集群扩展,缩减和集群维护7.     Ceph 基础知识的介绍,包括集群map,PG和身份验证8.     Ceph 集群的监控

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值