如何使用 VIPER 架构设置异步图像加载?

How to setup asynchronous image loading using VIPER artechiture?

应用程序的本质是一个 UITableView,当用户向下滚动 tableView 时,它会在每一行显示 UIImages。我应该如何在不破坏 VIPER 架构的情况下将图像加载到单元格中?

--VC code--

func cellForRowAtIndexPath...... {
    var cell = dequeueCellWithIdentifier.....

    //Method 1
    cell.image = outputInteracter.loadImage("someHttpImageLink")

    //Method 2. - using a completion block
    outputInteracter.loadImage(anImage -> {
        cell.image = anImage
    }
}

以上两种方法似乎都破坏了 VIP,因为演示者不参与并且 V-I-P 边界之间没有结构传递

您如何建议让 TableView 的 UIImages 进行异步调用以使用 VIP 下载图像(不阻塞主线程)?我可以使调用模式像这样,但我对第 4 步感到困惑:

  1. VC --> interacterOutput.loadImage("someLink")
  2. Interacter --> 完成获取图像的工作,并将 UIimage 发送给演示者
  3. Presenter --> UIImage 已经是 VC 的正确格式,因此将信息传递回 VC
  4. VC --> 我应该如何最好地设置代码,以便单元格知道它的图像已准备就绪?我不想重新加载整个 tableView

如有任何帮助,我们将不胜感激。

你所描述的场景并不是VIPER. In VIPER, the presenter is in the middle between the view and interactor. Your description is more closely to Clean Swift从 V 到 I 再到 P 的单向控制流。

假设你的问题是Clean Swift,你首先需要清楚业务逻辑是什么。在不知道您的应用程序详细信息的情况下,我只能假设您首先要求交互器获取 JSON 中的对象列表。每个对象都有一个 link 到某处的图像,然后您必须单独获取该图像。

如果我的假设是正确的,那么获取这些单独的图像并不是业务逻辑。它只是业务逻辑的一部分。业务逻辑是首先获取对象列表。

在 JSON 中收到对象列表后,您的演示者可以 assemble 视图模型对象来表示这些对象。图片 URLs 可以简单地表示为字符串而不是 UIImage.

如果您在将视图模型对象传回视图控制器之前等待获取所有这些图像,您的 UI 虽然在技术上没有被阻止,但在用户看到内容之前需要等待很长时间table 视图。因此,我会简单地将图像 URLs 传递给视图控制器。

视图控制器然后可以在不涉及交互器或演示器的情况下自行获取实际图像。出于性能原因,它可以使用 SDWebImage 之类的东西来获取和缓存图像。

并不是所有的东西都必须经过 VIP 周期。以下内容可能有所帮助。

将业务逻辑视为获取对象列表。一旦完成,业务逻辑就完成了。视图控制器可以选择向用户显示图像 URL 字符串,而不是实际图像。这当然是一种表现形式,尽管并不常见。但是您的视图控制器选择将图像显示为 UIImages。此显示仅在视图控制器内部。这实际上不是您的业务逻辑。

您的视图控制器可以自己获取图像。它甚至可以要求自定义子视图进行抓取。

您问题中的一个子问题是关于如果您要通过 VIP 周期单独获取图像,则不重新加载 table 视图。我不建议这样做。但是,如果您的对象列表实际上只是图像列表,如在相册集合视图中,这可能是必要的。我会将图像 URL、row/column 数据嵌入到交互器的请求对象中。当异步返回一张图片时,我就已经知道这张图片要显示在哪一行哪一列了。只需将其传递给演示者然后查看控制器即可。然后视图控制器可以只重新加载单个单元格而不是整个 table 或集合视图。

我希望这有助于阐明 VIPER、Clean Swift、VIP 周期以及什么是业务逻辑。