0

I'm learn to use RxSwift and RxDataSource to separate business logic from View Controller (using MVVM).

Suppose I want to create table view like in the Mail App in iOS, when user swipe left, there are delete button and More button.

In the normal MVC, I have to implement delegate method editActionsForRowAt.

public func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]?

        var swipeActions = [UITableViewRowAction]()
        let removeAction = UITableViewRowAction(style: .destructive, title: "Delete") { [weak self] (action, indexPath) in
            guard let strongSelf = self else { return }
            strongSelf.deleteBankAccountTrigger.onNext(indexPath)
            tableView.deleteRows(at: [indexPath], with: .fade)
        }
        swipeActions.append(removeAction)

        if *cellIsNotDefault* {
            let makeDefaultAction = UITableViewRowAction(style: .default, title: "Make Default") { [weak self] (action, indexPath) in
                guard let strongSelf = self else { return }
                strongSelf.makeBankAccountDefaultTrigger.onNext(indexPath)
            }

            makeDefaultAction.backgroundColor = UIColor.lightGray
            swipeActions.append(makeDefaultAction)
        }

        return swipeActions

I don't know how to move logic cellIsNotDefault from the delegate to ViewModel. Because I think the logic to show/hide SwipeAction button should be in ViewModel.

Any suggestion is welcome.

Thank you.

Update:

I tried to use RxDataSources, but still no clue for custom swipe action. For delete action, I can use tableView.rx.itemDeleted method to subscribe to it. But if I want to subscribe to the custom Swipe action (like my Make Default action). How to do that?

christopher.online
  • 2,614
  • 3
  • 28
  • 52
Jefferson Setiawan
  • 536
  • 1
  • 5
  • 22

1 Answers1

1

First of all, viewModel should contain just data that are displayed by particular view. So I'm not sure if viewModel should contain information about behaviour of your view ( in this case it means that your cell have some action ). Maybe I would encapsulate this logic to the model itself. I guess that you get from API something like isBankAccountDefault. If you don't get this attribute straight from API and you need some logic to determine it. You can create computed property inside your model and put there * cellIsNotDefault * logic.

But if you insist on having it in viewModel, you can create Bool property isBankAccountDefault in viewModel. Then you will put logic * cellIsNotDefault * to formatter, that is creating that viewModel and set isBankAccountDefault value accordingly to * cellIsNotDefault * logic.

Vojta
  • 810
  • 10
  • 16
  • Thanks for answering @user3797599. Yes I agree the viewModel should contain just data. So the if else statement is still in the VC. So I think, my question is wrong, I'm confused how to pass the value from ViewModel to the editActionsForRowAt method. I'm using [Clean Architecture Rx Swift](https://github.com/sergdort/CleanArchitectureRxSwift) Architecture Pattern. And the output is bind on the viewDidLoad. So how I get the value in the editActionsForRowAt? – Jefferson Setiawan May 07 '18 at 03:43
  • Hi Jef, sorry for not getting back to your question. I'm not so familiar with "Clean Architecture Rx Swift" and I didn't have time recently to get more into it. How did you solve your issue in the end? – Vojta May 21 '18 at 12:43
  • I ended up using `PublishSubject` to trigger the input to the View Model. When the user select the option, I trigger the publish subject on next and passing the model. – Jefferson Setiawan May 22 '18 at 04:45