结合 Alamofire 和 RxSwift
Posted
技术标签:
【中文标题】结合 Alamofire 和 RxSwift【英文标题】:Combining Alamofire and RxSwift 【发布时间】:2016-03-12 02:27:49 【问题描述】:我有这个Alamofire
的自定义实现:
protocol HTTPProtocol: class
typealias RequestType
typealias RespondType
func doRequest(requestData: RequestType) -> Self
func completionHandler(block:(Result<RespondType, NSError>) -> Void) -> Self
//example of a request:
locationInfo
//Make a request
.doRequest(HTTPLocationInfo.RequestType(coordinate: $0))
//Call back when request finished
.completionHandler result in
switch result
case .Success(let info): self.locationInfoRequestSuccess(info)
case .Failure(let error): self.locationInfoRequestFailed(error)
我想将 MVVM 和 RxSwift 应用到我的项目中。但是,我找不到合适的方法来做到这一点。
我想要实现的是一个ViewModel
和一个ViewController
可以做这些事情:
class ViewController
func googleMapDelegate(mapMoveToCoordinate: CLLocationCoordinate2D)
// Step 1: set new value on `viewModel.newCoordinate` and make a request
func handleViewModelCallBack(resultParam: ...*something*)
// Step 3: subscribeOn `viewModel.locationInfoResult` and do things.
class ViewModel
//Result if a wrapper object of Alamofire.
typealias LocationInfoResult = (Result<LocationInfo.Respond, NSError>) -> Void
let newCoordinate = Variable<CLLocationCoordinate2D>(kInvalidCoordinate)
let locationInfoResult: Observable<LocationInfoResult>
init()
// Step 2: on newCoordinate change, from step 1, request Location Info
// I could not find a solution at this step
// how to make a `completionHandler` set its result on `locationInfoResult`
非常感谢任何帮助。谢谢。
【问题讨论】:
你看过github.com/RxSwiftCommunity/RxAlamofire吗? 【参考方案1】:您可以使用@Gus 在评论中所说的RxAlamofire。但是,如果您使用的任何库默认不支持 Rx 扩展,您可能需要手动进行转换。
所以对于上面的代码 sn-p,你可以从你已经实现的回调处理程序中创建一个 observable
func getResultsObservable() -> Observable<Result>
return Observable.create (observer) -> Disposable in
locationInfo
//Make a request
.doRequest( .... )
//Call back when request finished
.completionHandler result in
switch result
case .Success(let info): observer.on(Event.Next(info))
case .Failure(let error): observer.on(Event.Error(NetworkError()))
return Disposables.create
// You can do some cleaning here
回调处理程序是观察者模式的实现,因此将其映射到自定义 Observable 是一个简单的操作。
一个好的做法是在disposing的情况下取消网络请求,例如这是一个完整的一次性Post请求:
return Observable<Result>.create (observer) -> Disposable in
let requestReference = Alamofire.request("request url",
method: .post,
parameters: ["par1" : val1, "par2" : val2])
.validate()
.responseJSON (response) in
switch response.result
case .success:
observer.onNext(response.map...)
observer.onCompleted()
case .failure:
observer.onError(NetworkError(message: response.error!.localizedDescription))
return Disposables.create(with:
requestReference.cancel()
)
注意:在swift 3之前Disposables.create()
被NopDisposable.instance
替换
【讨论】:
【参考方案2】:您似乎不需要订阅newCoordinate
,所以我会提出请求func
。
然后,使用您从 Alamofire 返回的信息,只需在 locationInfoResult
上设置值,您将在 ViewController
中获得新结果
class ViewController: UIViewController
func viewDidLoad()
super.viewDidLoad()
//subscribe to info changes
viewModel.locationInfoResult
.subscribeNext info in
//do something with info...
func googleMapDelegate(mapMoveToCoordinate: CLLocationCoordinate2D)
viewModel.requestLocationInfo(mapMoveToCoordinate)
class ViewModel
let locationInfoResult: Variable<LocationInfoResult?>(nil)
init()
func requestLocationInfo(location: CLLocationCoordinate2D)
//do Alamofire stuff to get info
//update with the result
locationInfoResult.value = //value from Alamofire
【讨论】:
以上是关于结合 Alamofire 和 RxSwift的主要内容,如果未能解决你的问题,请参考以下文章
Swift 3 的 ObjectMapper 和 Alamofire 问题 Alamofire 4 的 Alamofire 版本
在 Swift 中将 Alamofire 结果解析为对象(使用:Alamofire、SwiftyJSON 和 ObjectMapper)
Alamofire 自定义响应从 Alamofire v1.3 迁移到 3.0(和 Swift 2 语法)