ios - 结合 Alamofire 和 RxSwift

标签 ios swift mvvm rx-swift

我有这个 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`
    }
}

非常感谢任何帮助。谢谢。

最佳答案

您可以使用 RxAlamofire正如@Gus 在评论中所说。但是,如果您使用任何默认情况下不支持 Rx 扩展的库,您可能需要手动进行转换。

因此对于上面的代码片段,您可以从您已实现的回调处理程序创建一个可观察对象

    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 是一个直接的操作。

一个好的做法是在处理的情况下取消网络请求,例如这是一个完整的一次性 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

关于ios - 结合 Alamofire 和 RxSwift,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34134365/

相关文章:

swift - 类型 '()' 不符合协议(protocol) 'BooleanType'

wpf - Shift + 左键单击的事件触发器

c# - Listview滚动触发Combobox SelectedValue并抛出异常

ios - 如何查找给定字符串是否存在于 NSMutableDictionary 中

ios - iPad 2/Retina iPad,应用程序如何识别它在哪个设备上运行?

ios - 我可以在 Swift 5 和 IOS 12 中以编程方式更改 iOS 屏幕壁纸吗

Swift AnyClass 引用 Class 实例还是只是 Type?

objective-c - dealloc 后对象没有释放

swift - 仅使用 .animation 修饰符的显式动画不起作用

c# - 显示用户控件而不是文本 MVVM 的组合框