What is the best way to handle cell action in Viper architecture? Here is my basic VC:
class StoriesViewController: BaseViewController {
var presenter: StoriesPresenterInput?
private var stories: [Story] = [] {
didSet {
guard let contentView = self.contentView as? StoriesView else { return }
contentView.refresherControl.endRefreshing()
contentView.activityView.stopAnimating()
if stories.count == 0 {
contentView.collectionView.setNoDataPlaceholder()
} else {
contentView.collectionView.removeNoDataPlaceholder()
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.presenter?.viewDidLoad()
}
}
extension StoriesViewController: UICollectionViewDataSource, UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.stories.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "storiesCell", for: indexPath) as! StoriesCollectionViewCell
cell.story = stories[indexPath.item]
return cell
}
}
In classic MVC, i would create a protocol for tap and delegate in my cell:
protocol StoryCellProtocol: class {
func didTapUser(user: User)
}
class StoryCell: UICollectionViewCell {
weak var delegate: StoryCellProtocol?
}
The set delegate to my VC in cellForRow:
cell.delegate = self
How to do the same thing in VIPER?
CodePudding user response:
IMHO the best way would be to add the protocol conformance to your Presenter directly.
class StoriesPresenterInput: ..., StoryCellProtocol
and assign the delegate in cellForItem
:
cell.delegate = presenter
Since any user interaction should be parsed/processed in the presenter, you would also be effectively removing the (subjectively) redundant redirection between view and presenter.
CodePudding user response:
there is many good ways for that, assuming your input presenter is a protocol, a good one: set to the protocol for the action in cell, for example, setup the protocol for the action cell:
protocol CellAction {
didAction()
}
and configure your cell using a method in your cell class like:
func config(action: CellAction, story: Story) {
//todo
}
here is the tricky part, using your input to setting up the protocol to presenter, REMEMBER, ASUMING YOUR INPUT IS A PROTOCOL, using in cellForRow like:
let cellAction = presenter as! CellAction
cell.config(action: cellAction, story: story)
you need setup an extension for your presenter to set the protocol
extension YourPresenter: CellAction {
func didAction() {
//todo
}
}