应用程序的本质是一个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步感到困惑:
非常感谢任何帮助。
答案 0 :(得分:9)
您描述的情景并非如此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周期以及业务逻辑。