Swift 4.0中的网络层

每当我开始一个新项目时,都会出现相同的问题。 如何实现网络层? 使用Moya,Alamofire等外部库或从头开始编写它。

我对这个问题的回答是–使用不带任何第三方库的纯Swift。 当然,实现面向协议的层非常简单,使用enum键入safe来配置端点并完全可测试。 在这几点中,您将学习如何编写可定制的面向协议的网络层。

在开始之前,了解URLSession及其组成类很重要。 通常, URLSession负责发送和接收HTTPRequests 。 对于基本请求,您可以使用没有配置对象的shared会话。 它不像您自己创建的会话那样可定制,但是如果您有非常有限的要求,它可以作为一个很好的起点。 对于其他类型的会话,您URLSession使用以下三种配置之一实例化URLSession

  1. .default –会话表现为共享会话,但允许进行更多配置并使用委托增量获取数据。
  2. .ephemeral –会话也类似于共享会话,但是不要将缓存,cookie或凭据写入磁盘。
  3. .background –会话使您可以在应用程序未运行时在后台执行内容的上载和下载。

URLSession以两种方式返回数据:

  1. 完成处理程序
  2. 在委托上调用方法

在会话中,您可以创建URLSessionTask以从服务器检索数据,上传照片或下载文件。 此外,您还可以继续,暂停和取消任务。 URLSessionTask提供了暂停运行任务的机会,例如,当用户离开应用程序时暂停任务,并在返回时恢复任务。 URLSession提供三种类型的任务:

  1. data –使用Data对象发送和接收数据。 数据任务旨在向服务器发出简短的,经常是交互式的请求。
  2. upload –与数据任务相似,但通常用于在应用程序不运行时上传文件并支持后台上传。
  3. download –以文件形式检索数据,并在应用程序未运行时支持后台下载和上传。

在本教程中,您将仅使用第一种URLSessionTask来发送请求并处理服务器的响应。

简要回顾一下URLSession可以做什么URLSession ,现在让我们进行一些练习。

首先,您必须将网络层划分为小型服务。 将所有请求都保存在一个类/枚举中是很难维护的,并且可能会变成一个庞然大物。 ServiceProtocol将帮助创建URLRequestServiceProtocol包含构成组件,例如baseURL,路径,方法,标头,任务和parametersEncoding。 继续创建您的第一个简单网络层文件。

HTTPMethod是一个枚举,负责设置请求的HTTP方法。 URLRequest具有.httpMethod属性以设置方法的字符串类型。

Task是一个枚举,负责为特定服务配置参数。 您可以添加适用于您的网络层要求的情况。 例如upload(Data)download(parameters: Parameters)等。该示例只有两种情况可以发送普通请求或带有参数。

ParametersEncoding是负责设置编码类型的枚举。 在此示例中,您必须使用最流行的:URL和JSON。

瞧! 创建网络层的第一部分已经完成。 抬起头,继续前进! 让我们进入下一部分-如何实现URLRequest的构造函数。

在向API发送第一个请求之前,必须从ServiceProtocol创建自定义请求。 您可能已经注意到Service具有构造Request的所有信息。 为了避免创建新类,您将创建URLRequestURLComponents的扩展。

首先:创建URLComponents文件。 此扩展名将baseURL与path合并,并且如果参数编码为url,则将参数添加到url。 将此代码粘贴到您的文件中:

  1. 要获取完整的url路径,您需要将路径附加到基本url。
  2. 使用新的URL初始化URLComponents。
  3. 如果参数编码为“ url”且请求包含参数,则为每个参数创建[URLQueryItem]数组,并将其设置为queryItems。

下一步是URLRequest 。 创建文件并添加以下实现:

  1. 首先创建urlComponents。
  2. 使用新的urlComponent初始化URLRequest
  3. 将请求的httpMethod设置为与ServiceProtocol相等。
  4. 设置标题。
  5. 如果参数编码为“ json”,并且请求包含参数,请使用JSONSerialization字典,将参数包含在Data中。 您可以添加try catch闭包来处理异常。

下一部分完成了! 恭喜你!

当您从发送的请求中获得响应时,完成处理程序将返回不可读的信息。 可选数据,响应和错误什么也没说。 您必须创建枚举来处理来自API的响应并显示清晰的消息。 创建两个文件NetworkResponseNetworkError 。 有两种情况:

  1. .success –如果成功–返回“可降解模型”
  2. .error –如果错误–返回类型为NetworkError错误。

对于博客文章示例, NetworkError只有两种情况:

您的网络层几乎已完成。 最后需要实现的是提供者来发送请求。 为此,创建新文件ProviderProtocol并添加以下实现:

注意!:T必须符合可解码协议。

如果ProviderProtocol完成,现在您可以开始实现最后一个类URLSessionProvider ,这是网络层的核心。 为此:创建新文件并复制以下代码:

  1. URLSessionProvider符合之前几行创建的ProviderProtocol
  2. 这种方法对于测试网络层是必需的。 这很重要,因为您可以轻松地通过模拟文件切换会话并模拟无需Internet连接的来自API的响应。 在下一篇博文中,我将向您解释如何测试网络层。 现在,请创建一个新文件URLSessionProtocol并复制以下代码:

接下来,您将创建请求功能。 此功能负责我们网络层中的所有重要工作。 将此方法添加到URLSessionProvider

  1. 来自服务对象的初始化请求。
  2. 创建URLSessionDataTask以从API发送和接收数据。 数据任务旨在向服务器发出简短的,经常是交互式的请求。
  3. 开始任务。 会话将请求发送到服务器,并等待响应。
  4. handleDataResponse返回可选值,您实际上不知道请求是成功完成还是出错。 您需要额外的方法来解析响应数据和错误。
  1. 首先,您必须检查是否发生了错误。 如果您的API错误地返回了一些信息,请将自定义init添加到NetworkError枚举中并对其进行解析。
  2. 在这种情况下,所有请求都返回一个json数据,因此,如果响应为空,函数将返回错误
  3. HTTPURLResponse包含已发送请求的状态代码。 在此示例中,状态代码在200…299之间的请求在其他情况下均具有成功状态,但失败。
  4. 使用JSONDecoder解码响应数据并返回类型T的预期对象。

就这样! 您的网络层是在纯Swift中完成的,没有第三方库。 在下一部分中,您将了解如何创建简单服务并发送第一个请求。

在此演示中,您将使用免费的API(https://jsonplaceholder.typicode.com),该API可以获取帖子,评论和用户信息。 首先创建文件PostService并复制以下代码:

PostService实现两种情况:获取所有帖子和特定postId的评论。 对于这两种情况,您都使用“ GET”方法和“ url”参数编码。 “ all”情况不需要任何特殊参数,因此您可以使用普通请求,但对于“ comments”情况,则需要发送带有参数(键:“ postId”,值:Int)的请求。

最后,您准备发送您的第一个请求并使用已实现的提供程序! 打开ViewController并添加以下方法:

  1. 创建属性以对提供者有强烈的参考。
  2. 发送特定类型的请求。 在这种情况下,您想获取帖子列表,因此添加符合Decodable和Encodable协议的Post模型。

3.处理响应! 就这样! 🙂

您可以在此处下载本教程的完整项目:

marcinjackowski / NetworkLayer

通过在GitHub上创建一个帐户为marcinjackowski / NetworkLayer开发做出贡献。

github.com

如您所见,构建网络层无需使用逻辑复杂的第三方库。 该解决方案的最大优势在于它是纯快速编写的。 To您可以在此处下载本教程的完整项目。