Swift 4.0中的网络层
每当我开始一个新项目时,都会出现相同的问题。 如何实现网络层? 使用Moya,Alamofire等外部库或从头开始编写它。
我对这个问题的回答是–使用不带任何第三方库的纯Swift。 当然,实现面向协议的层非常简单,使用enum键入safe来配置端点并完全可测试。 在这几点中,您将学习如何编写可定制的面向协议的网络层。
在开始之前,了解URLSession
及其组成类很重要。 通常, URLSession
负责发送和接收HTTPRequests
。 对于基本请求,您可以使用没有配置对象的shared
会话。 它不像您自己创建的会话那样可定制,但是如果您有非常有限的要求,它可以作为一个很好的起点。 对于其他类型的会话,您URLSession
使用以下三种配置之一实例化URLSession
:
-
.default
–会话表现为共享会话,但允许进行更多配置并使用委托增量获取数据。 -
.ephemeral
–会话也类似于共享会话,但是不要将缓存,cookie或凭据写入磁盘。 -
.background
–会话使您可以在应用程序未运行时在后台执行内容的上载和下载。
URLSession以两种方式返回数据:
- 完成处理程序
- 在委托上调用方法
在会话中,您可以创建URLSessionTask
以从服务器检索数据,上传照片或下载文件。 此外,您还可以继续,暂停和取消任务。 URLSessionTask
提供了暂停运行任务的机会,例如,当用户离开应用程序时暂停任务,并在返回时恢复任务。 URLSession提供三种类型的任务:
-
data
–使用Data
对象发送和接收数据。 数据任务旨在向服务器发出简短的,经常是交互式的请求。 -
upload
–与数据任务相似,但通常用于在应用程序不运行时上传文件并支持后台上传。 -
download
–以文件形式检索数据,并在应用程序未运行时支持后台下载和上传。
在本教程中,您将仅使用第一种URLSessionTask
来发送请求并处理服务器的响应。
简要回顾一下URLSession
可以做什么URLSession
,现在让我们进行一些练习。
首先,您必须将网络层划分为小型服务。 将所有请求都保存在一个类/枚举中是很难维护的,并且可能会变成一个庞然大物。 ServiceProtocol
将帮助创建URLRequest
。 ServiceProtocol
包含构成组件,例如baseURL,路径,方法,标头,任务和parametersEncoding。 继续创建您的第一个简单网络层文件。
HTTPMethod是一个枚举,负责设置请求的HTTP方法。 URLRequest具有.httpMethod
属性以设置方法的字符串类型。
Task是一个枚举,负责为特定服务配置参数。 您可以添加适用于您的网络层要求的情况。 例如upload(Data)
, download(parameters: Parameters)
等。该示例只有两种情况可以发送普通请求或带有参数。
ParametersEncoding
是负责设置编码类型的枚举。 在此示例中,您必须使用最流行的:URL和JSON。
瞧! 创建网络层的第一部分已经完成。 抬起头,继续前进! 让我们进入下一部分-如何实现URLRequest的构造函数。
在向API发送第一个请求之前,必须从ServiceProtocol
创建自定义请求。 您可能已经注意到Service具有构造Request的所有信息。 为了避免创建新类,您将创建URLRequest
和URLComponents
的扩展。
首先:创建URLComponents
文件。 此扩展名将baseURL与path合并,并且如果参数编码为url,则将参数添加到url。 将此代码粘贴到您的文件中:
- 要获取完整的url路径,您需要将路径附加到基本url。
- 使用新的URL初始化URLComponents。
- 如果参数编码为“ url”且请求包含参数,则为每个参数创建[URLQueryItem]数组,并将其设置为queryItems。
下一步是URLRequest
。 创建文件并添加以下实现:
- 首先创建urlComponents。
- 使用新的urlComponent初始化
URLRequest
。 - 将请求的httpMethod设置为与
ServiceProtocol
相等。 - 设置标题。
- 如果参数编码为“ json”,并且请求包含参数,请使用
JSONSerialization
字典,将参数包含在Data中。 您可以添加try catch闭包来处理异常。
下一部分完成了! 恭喜你!
当您从发送的请求中获得响应时,完成处理程序将返回不可读的信息。 可选数据,响应和错误什么也没说。 您必须创建枚举来处理来自API的响应并显示清晰的消息。 创建两个文件NetworkResponse
和NetworkError
。 有两种情况:
-
.success
–如果成功–返回“可降解模型” -
.error
–如果错误–返回类型为NetworkError
错误。
对于博客文章示例, NetworkError
只有两种情况:
您的网络层几乎已完成。 最后需要实现的是提供者来发送请求。 为此,创建新文件ProviderProtocol
并添加以下实现:
注意!:T必须符合可解码协议。
如果ProviderProtocol
完成,现在您可以开始实现最后一个类URLSessionProvider
,这是网络层的核心。 为此:创建新文件并复制以下代码:
-
URLSessionProvider
符合之前几行创建的ProviderProtocol
。 - 这种方法对于测试网络层是必需的。 这很重要,因为您可以轻松地通过模拟文件切换会话并模拟无需Internet连接的来自API的响应。 在下一篇博文中,我将向您解释如何测试网络层。 现在,请创建一个新文件
URLSessionProtocol
并复制以下代码:
接下来,您将创建请求功能。 此功能负责我们网络层中的所有重要工作。 将此方法添加到URLSessionProvider
。
- 来自服务对象的初始化请求。
- 创建
URLSessionDataTask
以从API发送和接收数据。 数据任务旨在向服务器发出简短的,经常是交互式的请求。 - 开始任务。 会话将请求发送到服务器,并等待响应。
-
handleDataResponse
返回可选值,您实际上不知道请求是成功完成还是出错。 您需要额外的方法来解析响应数据和错误。
- 首先,您必须检查是否发生了错误。 如果您的API错误地返回了一些信息,请将自定义init添加到
NetworkError
枚举中并对其进行解析。 - 在这种情况下,所有请求都返回一个json数据,因此,如果响应为空,函数将返回错误
-
HTTPURLResponse
包含已发送请求的状态代码。 在此示例中,状态代码在200…299之间的请求在其他情况下均具有成功状态,但失败。 - 使用
JSONDecoder
解码响应数据并返回类型T的预期对象。
就这样! 您的网络层是在纯Swift中完成的,没有第三方库。 在下一部分中,您将了解如何创建简单服务并发送第一个请求。
在此演示中,您将使用免费的API(https://jsonplaceholder.typicode.com),该API可以获取帖子,评论和用户信息。 首先创建文件PostService
并复制以下代码:
PostService实现两种情况:获取所有帖子和特定postId的评论。 对于这两种情况,您都使用“ GET”方法和“ url”参数编码。 “ all”情况不需要任何特殊参数,因此您可以使用普通请求,但对于“ comments”情况,则需要发送带有参数(键:“ postId”,值:Int)的请求。
最后,您准备发送您的第一个请求并使用已实现的提供程序! 打开ViewController
并添加以下方法:
- 创建属性以对提供者有强烈的参考。
- 发送特定类型的请求。 在这种情况下,您想获取帖子列表,因此添加符合Decodable和Encodable协议的
Post
模型。
3.处理响应! 就这样! 🙂
您可以在此处下载本教程的完整项目:
marcinjackowski / NetworkLayer
通过在GitHub上创建一个帐户为marcinjackowski / NetworkLayer开发做出贡献。
github.com
如您所见,构建网络层无需使用逻辑复杂的第三方库。 该解决方案的最大优势在于它是纯快速编写的。 To您可以在此处下载本教程的完整项目。