【问题标题】:RXSwift flatmap that returns from an async completion handler从异步完成处理程序返回的 RXSwift 平面图
【发布时间】:2017-07-31 19:22:27
【问题描述】:

我正在尝试创建一个 searchBar,它通过带有请求的 MKLocalSearch 搜索地址并使用 RXSwift 并绑定到 RXCocoa

到目前为止,我已经完成了以下工作 1.过滤和去抖动以避免过多的请求:

let searchRes = searchBar.rx.text
    .orEmpty
    .filter { query in
        return query.characters.count > 4
    }
    .debounce(1, scheduler: MainScheduler.instance)
  1. 生成的字符串查询被 map:ed 创建一个 MKLocationSearch,然后 flatMapp:ed 返回一个 MKMapItems 数组,以便能够将该数组绑定到 tableView 的项目:

    searchRes.map{query -> MKLocalSearch in
        let request = MKLocalSearchRequest()
        request.naturalLanguageQuery = query
        request.region = self.mapView.region
        return MKLocalSearch(request: request)
    }.flatMapLatest{search -> Observable<[MKMapItem]> in
        search.start(completionHandler:{(response, error) in
            let items: Variable<[MKMapItem]> = Variable([])
            if let resp = response {
                //need to return the result form this
                // i.e. items.value = response.mapItems
            }
            //can not return from here since the request is async
        }
    }.bindTo //continue to bind to tableview
    

如何使用 RXSwift 做到这一点,我找不到任何相关示例

【问题讨论】:

    标签: swift rx-swift rx-cocoa


    【解决方案1】:

    您必须使用异步请求创建一个 Observable。您可以定义以下方法来做到这一点:

    func mapItems(for searchRequest: MKLocalSearch) -> Observable<[MKMapItem]> {
        return Observable.create { observer in
            searchRequest.start(completionHandler: { (response, error) in
                if let error = error {
                    observer.onError(error)
                } else {
                    let items = response?.mapItems ?? []
                    observer.onNext(items)
                    observer.onCompleted()
                }
            })
    
            return Disposables.create {
                searchRequest.cancel()
            }
        }
    }
    

    那么你就可以用flatMapLatest这个方法了:

    searchRes
        .map { query -> MKLocalSearch in
            let request = MKLocalSearchRequest()
            request.naturalLanguageQuery = query
            request.region = self.mapView.region
            return MKLocalSearch(request: request)
        }
        .flatMapLatest{ [unowned self] search -> Observable<[MKMapItem]> in
            self.mapItems(for: search)
        }
        .bindTo(....
    

    【讨论】:

    • 谢谢,还在探索RX的深度,这部分一直没有很好的记录
    猜你喜欢
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 2019-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-10
    相关资源
    最近更新 更多