So I have been researching RxSwift for a couple days, and am trying to create a simple app with it. I have bound the searchController of my table to the results, which feed into the cellForRowAt
function. How do I bind the alamofire response to each cell?
Which of these do I need to do?
- Use RxAlamofire to create an searchResultsArray
- Change searchResultsArray to a
Variable
and usetoObservable
? - Bind
response
orsearchResultsArray
to create each cell.
The function I need to use is:
.bind(to: self.tableView.rx.items(cellIdentifier: "cell", cellType: UITableViewCell.self)) { row, element, cell in
cell.textLabel?.text = "something"
}
This is my current RxSwift code:
let disposeBag = DisposeBag()
var searchResultsArray = [[String:String]]()
searchController.searchBar.rx.text.orEmpty.filter { text in
text.count >= 3
}.subscribe(onNext: { text in
searchRequest(search: text, searchType: "t:t") { response in
self.searchResultsArray = response
self.tableView.reloadData()
}
}).disposed(by: disposeBag)
This is my current cell creation function. showSearchResults
changes when the cancel button is clicked.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: UITableViewCell = {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "cell") else {
return UITableViewCell(style: .subtitle, reuseIdentifier: "cell")
}
return cell
}()
if self.shouldShowSearchResults {
cell.textLabel?.text = searchResultsArray[indexPath.row]["result"]!
cell.detailTextLabel?.text = searchResultsArray[indexPath.row]["location"]!
}
return cell
}
This is my current api request:
func searchRequest(search: String, searchType: String, completionHandler: @escaping ([[String: String]]) -> ()) {
let payload: [String: Any] = [
"q": search,
"fq": searchType,
"start": 0
]
let url = URL(string: "https://www.athletic.net/Search.aspx/runSearch")!
Alamofire.request(url, method: .post, parameters: payload, encoding: JSONEncoding.default).responseJSON { response in
let json = response.data
do {
var searchResults: [[String: String]] = []
let parsedJson = JSON(json!)
if let doc = try? Kanna.HTML(html: parsedJson["d"]["results"].stringValue, encoding: .utf8) {
for row in doc.css("td:nth-child(2)") {
let link = row.at_css("a.result-title-tf")!
let location = row.at_css("a[target=_blank]")!
let schoolID = link["href"]!.components(separatedBy: "=")[1]
searchResults.append(["location": location.text!, "result": link.text!, "id":schoolID])
}
}
completionHandler(searchResults)
} catch let error {
print(error)
}
}
}
I would like to replace the cellForRowAt with a RxSwift solution.
Based on the code you presented, use of Rx will give you something like this:
The
shouldShowSearchResults
feels out of place in that. But otherwise it looks good.The above assumes you wrap your searchRequest in a function that returns an observable like this:
The above is a standard pattern that wraps a function that uses a callback into a function that returns an
Observable
.