8, Editable table
1. Renderings
(1) After the program starts, the table will automatically load 5 pieces of random data. Click the "Refresh" button to regenerate another 5 pieces of data and display them.
(2) After clicking the "plus" icon, a random data will be added at the end of the current dataset and displayed.
(3) Click the "minus sign" icon on the left side of the cell to delete the row of data.
(4) Drag the control icon to the right of the cell to change the display order.


2. Sample code
(1) Because there are many editing operations, we first use enum to create a command enumeration, which defines various operations on tableView data.
//Define various operation commands enum TableEditingCommand { case setItems(items: [String]) //Set table data case addItem(item: String) //New data case moveItem(from: IndexPath, to: IndexPath) //mobile data case deleteItem(IndexPath) //Delete data }
(2) Next, define the ViewModel corresponding to tableView. In addition to saving the table data, it also contains the specific implementation of the four operation commands defined above.
//Define the ViewModel corresponding to the table struct TableViewModel { //Table data item fileprivate var items:[String] init(items: [String] = []) { self.items = items } //Execute the corresponding command and return the final result func execute(command: TableEditingCommand) -> TableViewModel { switch command { case .setItems(let items): print("Set up table data.") return TableViewModel(items: items) case .addItem(let item): print("New data item.") var items = self.items items.append(item) return TableViewModel(items: items) case .moveItem(let from, let to): print("Move data items.") var items = self.items items.insert(items.remove(at: from.row), at: to.row) return TableViewModel(items: items) case .deleteItem(let indexPath): print("Delete data items.") var items = self.items items.remove(at: indexPath.row) return TableViewModel(items: items) } } }
(3) The last is the main view controller code.
import UIKit import RxSwift import RxCocoa import RxDataSources class ViewController: UIViewController { //Refresh button @IBOutlet weak var refreshButton: UIBarButtonItem! //New button @IBOutlet weak var addButton: UIBarButtonItem! //form var tableView:UITableView! let disposeBag = DisposeBag() override func viewDidLoad() { super.viewDidLoad() //Create a table view self.tableView = UITableView(frame: self.view.frame, style:.plain) //Create a reused cell self.tableView!.register(UITableViewCell.self, forCellReuseIdentifier: "Cell") self.view.addSubview(self.tableView!) //Tabular model let initialVM = TableViewModel() //Refresh data command let refreshCommand = refreshButton.rx.tap.asObservable() .startWith(()) //Add this to load the data automatically for page initialization .flatMapLatest(getRandomResult) .map(TableEditingCommand.setItems) //New entry command let addCommand = addButton.rx.tap.asObservable() .map{ "\(arc4random())" } .map(TableEditingCommand.addItem) //Move position command let movedCommand = tableView.rx.itemMoved .map(TableEditingCommand.moveItem) //Delete entry command let deleteCommand = tableView.rx.itemDeleted.asObservable() .map(TableEditingCommand.deleteItem) //Bind cell data Observable.of(refreshCommand, addCommand, movedCommand, deleteCommand) .merge() .scan(initialVM) { (vm: TableViewModel, command: TableEditingCommand) -> TableViewModel in return vm.execute(command: command) } .startWith(initialVM) .map { [AnimatableSectionModel(model: "", items: $0.items)] } .share(replay: 1) .bind(to: tableView.rx.items(dataSource: ViewController.dataSource())) .disposed(by: disposeBag) } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) tableView.setEditing(true, animated: true) } //Get random data func getRandomResult() -> Observable<[String]> { print("Generate random data.") let items = (0 ..< 5).map {_ in "\(arc4random())" } return Observable.just(items) } } extension ViewController { //Create a table data source static func dataSource() -> RxTableViewSectionedAnimatedDataSource <AnimatableSectionModel<String, String>> { return RxTableViewSectionedAnimatedDataSource( //Set the animation effect of inserting, deleting and moving cells animationConfiguration: AnimationConfiguration(insertAnimation: .top, reloadAnimation: .fade, deleteAnimation: .left), configureCell: { (dataSource, tv, indexPath, element) in let cell = tv.dequeueReusableCell(withIdentifier: "Cell")! cell.textLabel?.text = "entry\(indexPath.row): \(element)" return cell }, canEditRowAtIndexPath: { _, _ in return true //Cells can be deleted }, canMoveRowAtIndexPath: { _, _ in return true //Cell movable } ) } }
RxSwift use walkthrough series
Original from: www.exchange.com reprint please keep the original link