网络和UI更新(快速3)

本教程的目的是说明如何使用Grand Central Dispatch (GCD)在后台线程中执行网络任务,而不会阻塞iOS应用程序的用户界面。 回想一下,在iOS中,对UI的每次更新都需要在主线程上进行,因此在主线程上执行网络任务会导致在处理网络请求时出现“冻结”的接口。

完成的产品

在本教程结束时,您将已经构建了一个应用程序,该应用程序可以从HTTP地址获取图像并将其显示给用户。 为了验证网络操作是在后台进行的,我们向应用程序添加了一个滑块,用于更改图像的不透明度。 请注意,更改图像的不透明度是对应用程序UI的更新。 因此,它需要在主线程中发生。 下面的屏幕快照显示了完成的应用程序的外观:

当用户按下“下一步”按钮时,将执行新的网络请求。 在处理请求时,微调器覆盖在图像上,但是为了显示网络请求是在后台发生的,我添加了一个滑块,用于更改图像的不透明度。 您可以在应用程序执行期间随时向上或向下移动滑块。 无论是否正在处理网络请求或图像是否已加载,UI都会正确更新。

项目设置

在本教程中,我们将不会使用情节提要。 如果您想查看有关此选择的说明,请观看此视频。 另外,为了设置这个项目,请查看我其他教程的前两个部分。 这些部分说明了如何设置新的Xcode项目,删除情节提要和设置主ViewController.swift。 此外,此处提供了此项目的完整源代码。

建立使用者介面

完成上述步骤后,您应该具有一个空的ViewController.swift,看起来像下面的代码块。 继续,然后按Xcode屏幕左上角的播放。 加载应用程序后,您应该在模拟器/设备上看到黑屏。

向我们的应用程序添加逻辑

让我们将以下实例变量添加到ViewController类的顶部。 第一个是String对象数组,其中包含一系列图像的URL。 第二个是整数,始终保留对所选当前图像的引用。 我们需要此变量以避免在用户按下next时两次显示相同的图像。

在应用程序的ViewController类中实现以下方法。 给定与数组中索引位置相对应的Int对象后,方法“ chooseImage()”将调度网络调用。 调用“ nextImageTouched()”方法可确保我们不会两次检索同一张图像,并调用“ chooseImage()”来生成网络请求。 触摸的下一个图像将附加到nextImageButton视图内的处理程序“ addTarget()”方法。 取消注释UIButton闭包中包含“ addTarget()”的行。

“ fetchImageFromURL(imageURL:URL)”方法利用了Grand Central Dispatch在后台线程中分派网络请求。 在“ DispatchQueue.global()。async”闭包中执行的代码有两个目的。 首先,它从后台线程中的URL异步获取图像。 然后,它使用“ DispatchQueue.main.async”访问主线程,并命令所显示的当前图像更改为新获取的图像。 重要的是,异步地分派此操作,以使滑块即使在加载新图片时也可以执行不透明度更改。 最后一步是将处理程序方法添加到滑块中,以便我们可以更新图像的不透明度。 通过取消注释“ addTarget()”方法来更新闭包语句,并实现一个附加方法,如下面的代码块所示。

另外,您可以在“ viewDidLoad()”方法中添加对“ chooseImage()”方法的调用,以便在应用程序出现时加载第一个图像。

结论

尝试完成应用程序的实现。 如果您需要访问源代码,请签出其GitHub存储库。 请注意,由于我们正在使用GCD,因此可以在获取新图像时更新UI。 我建议您测试一下此功能的方法是,在您用另一根手指点击下一个按钮的同时,继续用一个手指移动滑块。 这表明在后台线程中获取新图像时,图像的不透明度(UI更新)可以在主线程中更改。