【RxSwift 實踐系列 3/3】thinking in Rx- UITableView

上期:【RxSwift 實踐系列 2/3】thinking in Rx- Create和Drive的功能,咱們要實如今uitableview中cell上按鈕功能。一樣,咱們在cell上直接訂閱這個按鈕,當接受到點擊請求的時候,UserDefaults上去git

以下:github

searchFiled.rx.text
            .filter{
                ($0?.lengthOfBytes(using: .utf8))! > 0 //長度大於1
            }
            .throttle(0.5, scheduler: MainScheduler.instance) //延遲0.5秒再執行
            .flatMap{
                ListViewModel().searchFromApi(repositoryName:String(describing: $0!))
            }
            .asDriver(onErrorJustReturn: [])
            .drive(resultTableView.rx.items(cellIdentifier: "SearchTableViewCell", cellType: SearchTableViewCell.self)) {
                (tableView, element, cell) in
                cell.nameLabel.text = element.name
                cell.codeLabel.text = element.code
                cell.addBtn.rx.tap.subscribe(
                    onNext: {
                        var stocks = UserDefaults.standard.array(forKey: "stockSelected")  as! [String]
                        stocks.append(element.code)
                        UserDefaults.standard.set(stocks, forKey: "stockSelected")
                        cell.addBtn.setTitle("已關注", for: .normal)
                    }
                    ).disposed(by: rx.disposeBag) 
            }
            .disposed(by: rx.disposeBag)
複製代碼

可是實際操做上發現問題了,當搜索框輸入在不斷變化的時候,cell也是在不斷的刷新的,cell重用的時候,按鈕就會被屢次訂閱,形成嚴重的bug。這裏就要用到一個方法:prepareForReuseswift

private(set) var disposeBag = DisposeBag()
    //SearchTableViewCell中實現
    override func prepareForReuse() {
        super.prepareForReuse()
        disposeBag = DisposeBag()
    }
複製代碼

在每次重用cell的時候,咱們會釋放以前的disposeBag,而後會爲cell建立一個新的disposeBag對象,避免屢次訂閱.bash

cell.addBtn.rx.tap.subscribe(
        onNext: {
            var stocks = UserDefaults.standard.array(forKey: "stockSelected")  as! [String]
            stocks.append(element.code)
            UserDefaults.standard.set(stocks, forKey: "stockSelected")
            cell.addBtn.setTitle("已關注", for: .normal)
        }
        ).disposed(by: cell.disposeBag)//注意,這裏是cell的disposeBag
複製代碼

這樣咱們就實現了cell上按鈕的實現。網絡

image.png

最後就是首頁列表展現了,首頁的展現和搜索列表同樣,這裏就不囉嗦了,這裏有個難點是,股票的價格在不刷新tableview的狀況下更新,在日常的實現裏咱們只能使用刷新單個cell來實現了,來看看rx的實現方式:app

ListViewModel().getFromApi(repositoryName: "").subscribe(
    onNext:{ rs in Observable<[ListModel]>
        .just(rs)
        .bind(to: self.resultTableView.rx.items(cellIdentifier: "ListTableViewCell", cellType: ListTableViewCell.self)) {(_, model:ListModel, cell:ListTableViewCell) in
            
            //定時任務每兩秒執行一次
            Observable<Int>.interval(2, scheduler: MainScheduler.instance).subscribe { (event) in
                ListViewModel().getOne(repositoryName: model.symbol)
                .subscribe(
                    onNext:{ rs in Observable<ListModel>
                        .just(rs)
                        .subscribe{
                            cell.currentLabel.text = String(describing: rs.current)
                            cell.nameLabel.text = rs.name
                            cell.codeLabel.text = rs.code
                        }.disposed(by: self.rx.disposeBag)
                    }
                ).disposed(by: self.rx.disposeBag)
            }.disposed(by: self.rx.disposeBag)
        }.disposed(by: self.rx.disposeBag)
    }
).disposed(by: rx.disposeBag)

複製代碼

在綁定的cell裏面,對整個cell作一個定時任務interval,每秒獲取一次網絡數據,訂閱這個數據來更新cell的元素,從而實現了cell無刷新的更新。能夠說代碼上只增長了3行就實現了這個功能!ide

image.png

這個用rxSwift實現的添加股票代碼實時刷新價格的應用到這裏就完成了,能夠在這裏找到實例代碼。post

代碼裏面還有不少缺陷和須要優化的地方: 好比不少的if else能夠用rxSwift作的更簡潔、許多錯誤異常等並無處理,網絡受權的提示、添加股票代碼後首頁並無及時更新。你們能夠嘗試着用rxSwift繼續優化代碼。優化

三期連接:ui

【RxSwift 實踐系列 1/3】爲何使用RxSwift

【RxSwift 實踐系列 2/3】thinking in Rx- Create和Drive

【RxSwift 實踐系列 3/3】thinking in Rx- UITableView

相關文章
相關標籤/搜索