Imagine I have a viewForHeaderInSection
like this:
Note: This is currently written in MVP and I am trying to refactor it to VIPER
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
guard let header = tableView.dequeueReusableHeaderFooterView(withIdentifier: DetailsSectionHeaderView.identifier) as? DetailsSectionHeaderView,
let section = PresenterEnum.Sections(rawValue: section),
section != .fourth, let presenter = presenter else {
return nil
}
switch section {
case .first:
header.configure(StringConstants.first.localized, showButton: false, isSelected: false)
case .second:
let secondArray = presenter.secondArrayCount
header.configure(StringConstants.second.localized, showButton: secondArray > 3, isSelected: presenter.isExpanded(section.rawValue))
header.showMoreAction = { [weak self] in
self?.handleMoreAction(tableView, in: section.rawValue)
}
case .third:
let thirdCount = presenter.thirdArrayCount
header.configure(StringConstants.third.localized, showButton: thirdArrayCount > 3, isSelected: presenter.isExpanded(section.third))
header.showMoreAction = { [weak self] in
self?.handleMoreAction(tableView, in: section.rawValue)
}
default:
return nil
}
return header
}
private func handleMoreAction(_ tableView : UITableView, in section : Int){
guard let presenter = presenter else {return}
tableView.beginUpdates()
let isExpanded = presenter.isExpanded(section)
var indexPaths = [IndexPath]()
for i in presenter.minimumRowCount..<presenter.totalRowCountForSection(section){
indexPaths.append([section, i])
}
if isExpanded{
tableView.deleteRows(at: indexPaths, with: .automatic)
}else{
tableView.insertRows(at: indexPaths, with: .automatic)
}
presenter.updateExpansion(section)
tableView.endUpdates()
}
UITableViewDelegate
and UITableViewDataSource
are part of the View
. But they are passive and shouldn't really request information from the presenter
. But at the same time the HOW to display a view information belongs to the presenter
.
Going by the definition above I can't figure out how to refactor the code below. It seems incorrect cause the logic about what the section should display is inside the view and how to handle the showMoreAction
as well.
So my question is: What is the "correct" way of structuring the above two methods to make it more VIPER compliant?
1 Create protocol which allows view and presenter to pass data, example :
Create weak view controller reference in the Presenter, that conforms Presenter protocol, expample:
Now when you assign tableview delegate and data source to presenter you can make an extension, example:
Then you should change your view(ViewController)
So you assigned your vc to the presenter's viewController Now all you need is to conform your VC to PresenterProtocol
Now your VC is clean, and all logic contains in presenter, sure thing it can be much easier, but I just showing the right direction