4

该应用程序的本质是一个 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,因为没有参与演示者,并且在 VIP 的边界之间没有传递任何结构

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

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

任何帮助将不胜感激。

4

1 回答 1

13

您描述的场景不是VIPER。在 VIPER 中,演示者位于视图和交互者之间。您的描述更接近于Clean Swift,它具有从 V 到 I 到 P 的单向控制流。

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

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

一旦以 JSON 格式接收到对象列表,您的演示者就可以组装一个视图模型对象来表示这些对象。图像 URL 可以简单地表示为 String 而不是 UIImage。

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

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

并非所有事情都必须经过 VIP 周期。以下可能会有所帮助。

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

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

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

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

于 2016-01-21T03:50:01.237 回答