使用 RxSwift 将 Alamofire 请求绑定到表视图

Posted

技术标签:

【中文标题】使用 RxSwift 将 Alamofire 请求绑定到表视图【英文标题】:Bind Alamofire request to table view using RxSwift 【发布时间】:2018-10-04 23:23:13 【问题描述】:

所以我已经研究了几天 RxSwift,并试图用它创建一个简单的应用程序。我已将我的表的 searchController 绑定到结果,这些结果会输入到 cellForRowAt 函数中。如何将 alamofire 响应绑定到每个单元格? 我需要做哪些?

使用 RxAlamofire 创建一个 searchResultsArray 将 searchResultsArray 更改为 Variable 并使用 toObservable? 绑定responsesearchResultsArray 以创建每个单元格。

我需要使用的函数是:

.bind(to: self.tableView.rx.items(cellIdentifier: "cell", cellType: UITableViewCell.self))   row, element, cell in
    cell.textLabel?.text = "something"

这是我当前的 RxSwift 代码:

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)

这是我当前的单元格创建功能。当点击取消按钮时,showSearchResults 会发生变化。

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

这是我当前的 api 请求:

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)
        
    

我想用 RxSwift 解决方案替换 cellForRowAt。

【问题讨论】:

【参考方案1】:

根据您提供的代码,使用 Rx 将为您提供如下内容:

override func viewDidLoad() 
    super.viewDidLoad()

    searchController.searchBar.rx.text.orEmpty
        .filter  text in text.count >= 3 
        .flatMapLatest  text in searchRequest(search: text, searchType: "t:t") 
        .bind(to: self.tableView.rx.items(cellIdentifier: "cell", cellType: UITableViewCell.self))   row, element, cell in
            if self.shouldShowSearchResults 
                cell.textLabel?.text = element["result"]!
                cell.detailTextLabel?.text = element["location"]!
            
        
        .disposed(by: disposeBag)

shouldShowSearchResults 在其中感觉格格不入。但除此之外它看起来不错。

以上假设您将 searchRequest 包装在一个返回可观察对象的函数中,如下所示:

func searchRequest(search: String, searchType: String) -> Observable<[[String: String]]> 
    return Observable.create  observer in
        searchRequest(search: search, searchType: searchType, completionHandler:  result in
            observer.onNext(result)
            observer.onCompleted()
        )
        return Disposables.create()
    

上面是一个标准模式,它将使用回调的函数包装到返回Observable的函数中。

【讨论】:

太棒了!用 Observable 替换闭包对我来说更好吗?我该怎么做呢? 我希望 RxAlamofire 已经编写了包装器,但我通常不使用 alamofire,所以我不确定。 您可能还喜欢查看这个示例程序。 github.com/dtartaglia/RxEarthquake我很乐意回答您对此的任何问题,只需发布​​问题,我会回答。 如果它返回Observable&lt;[String: String]> 怎么办? 表格视图需要一个对象数组。

以上是关于使用 RxSwift 将 Alamofire 请求绑定到表视图的主要内容,如果未能解决你的问题,请参考以下文章

如何将 RxSwift 与 AlamoFire 和 SwiftyJSON 一起使用?

如何使用 RxSwift 和 Alamofire 使用分页?

如何使用 RxSwift 和 Alamofire 库调用来自另一个 API 的响应的 API?

Alamofire 重试请求 - 反应方式

RxSwift+Alamofire 自定义映射器错误处理

如何使用 RxSwift 和 alamofire 获得嵌套 api 调用的响应?