I have an array of numbers, and I want the tableview
to show the number(s) that I entered in searchbar. This is my code, I don't know what shall I write in the line after (instead of) .subscribe
let dataSource = BehaviorRelay(value: [String]())
let disposeBag = DisposeBag()
var numbers = ["1", "2", "3", "4", "5"]
override func viewDidLoad() {
super.viewDidLoad()
dataSource.accept(numbers)
searchBar.rx.text.orEmpty
.throttle(.milliseconds(2000), scheduler: MainScheduler.instance)
.filter{self.numbers.contains($0)}
.subscribe(onNext:
})
self.dataSource
.asObservable()
.bind(to: tableView.rx.items(cellIdentifier: "Cell", cellType: TableViewCell.self)) {(row, element, cell) in
cell.textLabel?.text = element
}
.disposed(by: disposeBag)
Maybe it doesn't work because of other reasons, anyway thank you for help
You want to look at reactive code as a cause->effect chain. Some side-effect happens that causes some other side-effect. Of course between the cause and effect you have business logic.
Note firstly, that there is no need for the Subject. In the book Intro To Rx we learn:
Subjects provide a convenient way to poke around Rx, however they are not recommended for day to day use.
Now that we are thinking "cause to effect"... What is the effect we want to achieve? That would be the output of the table view which:
That's three causes and the logic defining how the causes affect the effect.
final class Example: UIViewController {
var searchBar: UISearchBar!
var addButton: UIButton!
var deleteButton: UIButton!
var tableView: UITableView!
let disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
enum Input {
case add
case delete
}
let initial = ["1", "2", "3", "4", "5"] // this is what we start with
Observable.merge(
addButton.rx.tap.map { Input.add }, // flag addButton taps for adding a number
deleteButton.rx.tap.map { Input.delete } // flag deleteButton taps for deleting a number
)
.scan(into: initial) { state, input in // setup a state machine that:
switch input {
case .add:
state.append("\(state.count + 1)") // adds a number when the add event happens
case .delete:
state.removeLast() // removes the last number when a delete event happens
}
}
.withLatestFrom(searchBar.rx.text) { list, text in
list.filter { $0 == text } // here we filter the list based on the value in the search bar
}
.startWith(initial) // show the initial values at start
.bind(to: tableView.rx.items(cellIdentifier: "Cell", cellType: UITableViewCell.self)) { _, element, cell in
cell.textLabel?.text = element
}
.disposed(by: disposeBag)
}
}
You may want to make the filter more or less complex than what I have above. To make the above testable, just move the closures out into separate functions so they can be tested independently.