接上期:【RxSwift 實踐系列 2/3】thinking in Rx- Create和Drive的功能,我們要實現在uitableview中cell上按鈕功能。同樣,我們在cell上直接訂閱這個按鈕,當接受到點選請求的時候,UserDefaults上去
如下:
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。這裡就要用到一個方法:prepareForReuse
private(set) var disposeBag = DisposeBag()
//SearchTableViewCell中實現
override func prepareForReuse() {
super.prepareForReuse()
disposeBag = DisposeBag()
}
複製程式碼
在每次重用cell的時候,我們會釋放之前的disposeBag,然後會為cell建立一個新的disposeBag物件,避免多次訂閱.
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上按鈕的實現。
最後就是首頁列表展示了,首頁的展示和搜尋列表一樣,這裡就不囉嗦了,這裡有個難點是,股票的價格在不重新整理tableview的情況下更新,在平常的實現裡我們只能使用重新整理單個cell來實現了,來看看rx的實現方式:
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行就實現了這個功能!
這個用rxSwift實現的新增股票程式碼實時重新整理價格的應用到這裡就完成了,可以在這裡找到例項程式碼。
程式碼裡面還有很多缺陷和需要優化的地方: 比如很多的if else可以用rxSwift做的更簡潔、許多錯誤異常等並沒有處理,網路授權的提示、新增股票程式碼後首頁並沒有及時更新。大家可以嘗試著用rxSwift繼續優化程式碼。
三期連結:
【RxSwift 實踐系列 1/3】為什麼使用RxSwift