Detailed explanation of Swift - RxSwift 34 (use of UITableView 5: editable table)

Keywords: Mobile

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

Posted by joshmmo on Fri, 03 Apr 2020 00:47:52 -0700