The nature of the app is a UITableView that displays UIImages on every row as the user scrolls down the tableView. How should i load the image into the cell without breaking VIPER architecture?
--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
}
}
Both methods above seem to break VIP, since the presenter is not involved and no structures are passed between boundaries of V-I-P
How would you suggest getting the UIImages of the TableView to make asynchronous calls to get the images downloaded (without blocking main thread) using VIP? I can make the call pattern be like this, but I am confused on step #4:
Any help would be greatly appreciated.
The scenario you described isn't so much VIPER. In VIPER, the presenter is in the middle between the view and interactor. Your description is more closely to Clean Swift with its unidirectional flow of control from V to I to P.
Assuming your question is for Clean Swift, you first need to be clear about what the business logic is. Without knowing the details of your app, I can only assume you first ask the interactor to fetch a list of objects in JSON. Each object has a link to an image somewhere which you then have to fetch separately.
If my assumptions are correct, fetching these individual images isn't the business logic. It is simply one part of the business logic. The business logic is to fetch the list of objects in the first place.
Once the list of objects is received in JSON, your presenter can assemble a view model object to represent these objects. The image URLs can be represented simply as String instead of UIImage.
If you wait to fetch all these images before you pass the view model object back to the view controller, your UI, although not technically being blocked, will have a long wait before the user sees content in the table view. Therefore, I would simply pass the image URLs to the view controller.
The view controller can then fetch the actual images all in itself without involving the interactor or the presenter. It can use something like SDWebImage to fetch and cache the images for performance reason.
Not everything has to go through the VIP cycle. The following may help.
Think of the business logic as fetching the list of objects. Once that's done, the business logic is fulfilled. The view controller can choose to display the image URL strings, not the actual images, to the user. That's certainly one representation, although not common. But your view controller chooses to display the images as UIImages. This displaying is only internal to the view controller. It isn't really your business logic.
Your view controller can fetch the images itself. It can even asks a custom subview to do the fetching.
A subquestion in your question is about not reloading the table view if you were to fetch the images individually going through the VIP cycle. I wouldn't recommend doing this. But if your list of objects is actually just a list of images, as in a photo album collection view, this may be necessary. I would embed the image URL, the row/column data in a request object to the interactor. When an image is returned asynchronously, I would already know which row and column this image is to be displayed at. Just pass that along to the presenter then view controller. The view controller can then just reload a single cell instead of the whole table or collection view.
I hope this helps clarify VIPER, Clean Swift, VIP cycle, and what business logic is.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With