From 4fac18335e00b45b317fbb0cc3a8958c758e4e5e Mon Sep 17 00:00:00 2001 From: Geonu Jeon Date: Mon, 2 Mar 2020 14:19:04 +0900 Subject: [PATCH] use return type `single` instead of `observable` --- Sources/RxAlamofire.swift | 1431 ++++++++++++++++++------------------- 1 file changed, 712 insertions(+), 719 deletions(-) diff --git a/Sources/RxAlamofire.swift b/Sources/RxAlamofire.swift index 8ed02938..5194c3ae 100644 --- a/Sources/RxAlamofire.swift +++ b/Sources/RxAlamofire.swift @@ -23,7 +23,7 @@ public let RxAlamofireUnknownError = NSError(domain: "RxAlamofireDomain", code: /** Creates a NSMutableURLRequest using all necessary parameters. - + - parameter method: Alamofire method object - parameter url: An object adopting `URLConvertible` - parameter parameters: A dictionary containing all necessary options @@ -37,34 +37,34 @@ public func urlRequest(_ method: Alamofire.HTTPMethod, parameters: [String: Any]? = nil, encoding: ParameterEncoding = URLEncoding.default, headers: [String: String]? = nil) - throws -> Foundation.URLRequest { - var mutableURLRequest = Foundation.URLRequest(url: try url.asURL()) - mutableURLRequest.httpMethod = method.rawValue - - if let headers = headers { - for (headerField, headerValue) in headers { - mutableURLRequest.setValue(headerValue, forHTTPHeaderField: headerField) - } - } - - if let parameters = parameters { - mutableURLRequest = try encoding.encode(mutableURLRequest, with: parameters) - } - - return mutableURLRequest + throws -> Foundation.URLRequest { + var mutableURLRequest = Foundation.URLRequest(url: try url.asURL()) + mutableURLRequest.httpMethod = method.rawValue + + if let headers = headers { + for (headerField, headerValue) in headers { + mutableURLRequest.setValue(headerValue, forHTTPHeaderField: headerField) + } + } + + if let parameters = parameters { + mutableURLRequest = try encoding.encode(mutableURLRequest, with: parameters) + } + + return mutableURLRequest } // MARK: Request /** Creates an observable of the generated `Request`. - + - parameter method: Alamofire method object - parameter url: An object adopting `URLConvertible` - parameter parameters: A dictionary containing all necessary options - parameter encoding: The kind of encoding used to process parameters - parameter header: A dictionary containing all the additional headers - + - returns: An observable of a the `Request` */ public func request(_ method: Alamofire.HTTPMethod, @@ -72,36 +72,36 @@ public func request(_ method: Alamofire.HTTPMethod, parameters: [String: Any]? = nil, encoding: ParameterEncoding = URLEncoding.default, headers: [String: String]? = nil) - -> Observable { - return SessionManager.default.rx.request(method, - url, - parameters: parameters, - encoding: encoding, - headers: headers) + -> Single { + return SessionManager.default.rx.request(method, + url, + parameters: parameters, + encoding: encoding, + headers: headers) } /** Creates an observable of the generated `Request`. - + - parameter urlRequest: An object adopting `URLRequestConvertible` - + - returns: An observable of a the `Request` */ -public func request(_ urlRequest: URLRequestConvertible) -> Observable { - return SessionManager.default.rx.request(urlRequest: urlRequest) +public func request(_ urlRequest: URLRequestConvertible) -> Single { + return SessionManager.default.rx.request(urlRequest: urlRequest) } // MARK: data /** Creates an observable of the `(NSHTTPURLResponse, NSData)` instance. - + - parameter method: Alamofire method object - parameter url: An object adopting `URLConvertible` - parameter parameters: A dictionary containing all necessary options - parameter encoding: The kind of encoding used to process parameters - parameter header: A dictionary containing all the additional headers - + - returns: An observable of a tuple containing `(NSHTTPURLResponse, NSData)` */ public func requestData(_ method: Alamofire.HTTPMethod, @@ -109,34 +109,34 @@ public func requestData(_ method: Alamofire.HTTPMethod, parameters: [String: Any]? = nil, encoding: ParameterEncoding = URLEncoding.default, headers: [String: String]? = nil) - -> Observable<(HTTPURLResponse, Data)> { - return SessionManager.default.rx.responseData(method, - url, - parameters: parameters, - encoding: encoding, - headers: headers) + -> Single<(HTTPURLResponse, Data)> { + return SessionManager.default.rx.responseData(method, + url, + parameters: parameters, + encoding: encoding, + headers: headers) } /** Creates an observable of the `(NSHTTPURLResponse, NSData)` instance. - + - parameter urlRequest: An object adopting `URLRequestConvertible` - + - returns: An observable of a tuple containing `(NSHTTPURLResponse, NSData)` */ -public func requestData(_ urlRequest: URLRequestConvertible) -> Observable<(HTTPURLResponse, Data)> { - return request(urlRequest).flatMap { $0.rx.responseData() } +public func requestData(_ urlRequest: URLRequestConvertible) -> Single<(HTTPURLResponse, Data)> { + return request(urlRequest).flatMap { $0.rx.responseData() } } /** Creates an observable of the returned data. - + - parameter method: Alamofire method object - parameter url: An object adopting `URLConvertible` - parameter parameters: A dictionary containing all necessary options - parameter encoding: The kind of encoding used to process parameters - parameter header: A dictionary containing all the additional headers - + - returns: An observable of `NSData` */ public func data(_ method: Alamofire.HTTPMethod, @@ -144,25 +144,25 @@ public func data(_ method: Alamofire.HTTPMethod, parameters: [String: Any]? = nil, encoding: ParameterEncoding = URLEncoding.default, headers: [String: String]? = nil) - -> Observable { - return SessionManager.default.rx.data(method, - url, - parameters: parameters, - encoding: encoding, - headers: headers) + -> Single { + return SessionManager.default.rx.data(method, + url, + parameters: parameters, + encoding: encoding, + headers: headers) } // MARK: string /** Creates an observable of the returned decoded string and response. - + - parameter method: Alamofire method object - parameter url: An object adopting `URLConvertible` - parameter parameters: A dictionary containing all necessary options - parameter encoding: The kind of encoding used to process parameters - parameter header: A dictionary containing all the additional headers - + - returns: An observable of the tuple `(NSHTTPURLResponse, String)` */ public func requestString(_ method: Alamofire.HTTPMethod, @@ -170,34 +170,34 @@ public func requestString(_ method: Alamofire.HTTPMethod, parameters: [String: Any]? = nil, encoding: ParameterEncoding = URLEncoding.default, headers: [String: String]? = nil) - -> Observable<(HTTPURLResponse, String)> { - return SessionManager.default.rx.responseString(method, - url, - parameters: parameters, - encoding: encoding, - headers: headers) + -> Single<(HTTPURLResponse, String)> { + return SessionManager.default.rx.responseString(method, + url, + parameters: parameters, + encoding: encoding, + headers: headers) } /** Creates an observable of the returned decoded string and response. - + - parameter urlRequest: An object adopting `URLRequestConvertible` - + - returns: An observable of the tuple `(NSHTTPURLResponse, String)` */ -public func requestString(_ urlRequest: URLRequestConvertible) -> Observable<(HTTPURLResponse, String)> { - return request(urlRequest).flatMap { $0.rx.responseString() } +public func requestString(_ urlRequest: URLRequestConvertible) -> Single<(HTTPURLResponse, String)> { + return request(urlRequest).flatMap { $0.rx.responseString() } } /** Creates an observable of the returned decoded string. - + - parameter method: Alamofire method object - parameter url: An object adopting `URLConvertible` - parameter parameters: A dictionary containing all necessary options - parameter encoding: The kind of encoding used to process parameters - parameter header: A dictionary containing all the additional headers - + - returns: An observable of `String` */ public func string(_ method: Alamofire.HTTPMethod, @@ -205,25 +205,25 @@ public func string(_ method: Alamofire.HTTPMethod, parameters: [String: Any]? = nil, encoding: ParameterEncoding = URLEncoding.default, headers: [String: String]? = nil) - -> Observable { - return SessionManager.default.rx.string(method, - url, - parameters: parameters, - encoding: encoding, - headers: headers) + -> Single { + return SessionManager.default.rx.string(method, + url, + parameters: parameters, + encoding: encoding, + headers: headers) } // MARK: JSON /** Creates an observable of the returned decoded JSON as `AnyObject` and the response. - + - parameter method: Alamofire method object - parameter url: An object adopting `URLConvertible` - parameter parameters: A dictionary containing all necessary options - parameter encoding: The kind of encoding used to process parameters - parameter header: A dictionary containing all the additional headers - + - returns: An observable of the tuple `(NSHTTPURLResponse, AnyObject)` */ public func requestJSON(_ method: Alamofire.HTTPMethod, @@ -231,34 +231,34 @@ public func requestJSON(_ method: Alamofire.HTTPMethod, parameters: [String: Any]? = nil, encoding: ParameterEncoding = URLEncoding.default, headers: [String: String]? = nil) - -> Observable<(HTTPURLResponse, Any)> { - return SessionManager.default.rx.responseJSON(method, - url, - parameters: parameters, - encoding: encoding, - headers: headers) + -> Single<(HTTPURLResponse, Any)> { + return SessionManager.default.rx.responseJSON(method, + url, + parameters: parameters, + encoding: encoding, + headers: headers) } /** Creates an observable of the returned decoded JSON as `AnyObject` and the response. - + - parameter urlRequest: An object adopting `URLRequestConvertible` - + - returns: An observable of the tuple `(NSHTTPURLResponse, AnyObject)` */ -public func requestJSON(_ urlRequest: URLRequestConvertible) -> Observable<(HTTPURLResponse, Any)> { - return request(urlRequest).flatMap { $0.rx.responseJSON() } +public func requestJSON(_ urlRequest: URLRequestConvertible) -> Single<(HTTPURLResponse, Any)> { + return request(urlRequest).flatMap { $0.rx.responseJSON() } } /** Creates an observable of the returned decoded JSON. - + - parameter method: Alamofire method object - parameter url: An object adopting `URLConvertible` - parameter parameters: A dictionary containing all necessary options - parameter encoding: The kind of encoding used to process parameters - parameter header: A dictionary containing all the additional headers - + - returns: An observable of the decoded JSON as `Any` */ public func json(_ method: Alamofire.HTTPMethod, @@ -266,12 +266,12 @@ public func json(_ method: Alamofire.HTTPMethod, parameters: [String: Any]? = nil, encoding: ParameterEncoding = URLEncoding.default, headers: [String: String]? = nil) - -> Observable { - return SessionManager.default.rx.json(method, - url, - parameters: parameters, - encoding: encoding, - headers: headers) + -> Single { + return SessionManager.default.rx.json(method, + url, + parameters: parameters, + encoding: encoding, + headers: headers) } // MARK: Upload @@ -279,37 +279,37 @@ public func json(_ method: Alamofire.HTTPMethod, /** Returns an observable of a request using the shared manager instance to upload a specific file to a specified URL. The request is started immediately. - + - parameter urlRequest: The request object to start the upload. - paramenter file: An instance of NSURL holding the information of the local file. - returns: The observable of `UploadRequest` for the created request. */ -public func upload(_ file: URL, urlRequest: URLRequestConvertible) -> Observable { - return SessionManager.default.rx.upload(file, urlRequest: urlRequest) +public func upload(_ file: URL, urlRequest: URLRequestConvertible) -> Single { + return SessionManager.default.rx.upload(file, urlRequest: urlRequest) } /** Returns an observable of a request using the shared manager instance to upload any data to a specified URL. The request is started immediately. - + - parameter urlRequest: The request object to start the upload. - paramenter data: An instance of NSData holdint the data to upload. - returns: The observable of `UploadRequest` for the created request. */ -public func upload(_ data: Data, urlRequest: URLRequestConvertible) -> Observable { - return SessionManager.default.rx.upload(data, urlRequest: urlRequest) +public func upload(_ data: Data, urlRequest: URLRequestConvertible) -> Single { + return SessionManager.default.rx.upload(data, urlRequest: urlRequest) } /** Returns an observable of a request using the shared manager instance to upload any stream to a specified URL. The request is started immediately. - + - parameter urlRequest: The request object to start the upload. - paramenter stream: The stream to upload. - returns: The observable of `Request` for the created upload request. */ -public func upload(_ stream: InputStream, urlRequest: URLRequestConvertible) -> Observable { - return SessionManager.default.rx.upload(stream, urlRequest: urlRequest) +public func upload(_ stream: InputStream, urlRequest: URLRequestConvertible) -> Single { + return SessionManager.default.rx.upload(stream, urlRequest: urlRequest) } // MARK: Download @@ -321,8 +321,8 @@ public func upload(_ stream: InputStream, urlRequest: URLRequestConvertible) -> - returns: The observable of `DownloadRequest` for the created download request. */ public func download(_ urlRequest: URLRequestConvertible, - to destination: @escaping DownloadRequest.DownloadFileDestination) -> Observable { - return SessionManager.default.rx.download(urlRequest, to: destination) + to destination: @escaping DownloadRequest.DownloadFileDestination) -> Single { + return SessionManager.default.rx.download(urlRequest, to: destination) } // MARK: Resume Data @@ -330,7 +330,7 @@ public func download(_ urlRequest: URLRequestConvertible, /** Creates a request using the shared manager instance for downloading from the resume data produced from a previous request cancellation. - + - parameter resumeData: The resume data. This is an opaque data blob produced by `NSURLSessionDownloadTask` when a task is cancelled. See `NSURLSession -downloadTaskWithResumeData:` for additional information. @@ -338,8 +338,8 @@ public func download(_ urlRequest: URLRequestConvertible, - returns: The observable of `Request` for the created download request. */ public func download(resumeData: Data, - to destination: @escaping DownloadRequest.DownloadFileDestination) -> Observable { - return SessionManager.default.rx.download(resumeData: resumeData, to: destination) + to destination: @escaping DownloadRequest.DownloadFileDestination) -> Single { + return SessionManager.default.rx.download(resumeData: resumeData, to: destination) } // MARK: Manager - Extension of Manager @@ -347,13 +347,13 @@ public func download(resumeData: Data, extension SessionManager: ReactiveCompatible {} protocol RxAlamofireRequest { - func responseWith(completionHandler: @escaping (RxAlamofireResponse) -> Void) - func resume() - func cancel() + func responseWith(completionHandler: @escaping (RxAlamofireResponse) -> Void) + func resume() + func cancel() } protocol RxAlamofireResponse { - var error: Error? { get } + var error: Error? { get } } extension DefaultDataResponse: RxAlamofireResponse {} @@ -361,700 +361,693 @@ extension DefaultDataResponse: RxAlamofireResponse {} extension DefaultDownloadResponse: RxAlamofireResponse {} extension DataRequest: RxAlamofireRequest { - func responseWith(completionHandler: @escaping (RxAlamofireResponse) -> Void) { - response { response in - completionHandler(response) + func responseWith(completionHandler: @escaping (RxAlamofireResponse) -> Void) { + response { response in + completionHandler(response) + } } - } } extension DownloadRequest: RxAlamofireRequest { - func responseWith(completionHandler: @escaping (RxAlamofireResponse) -> Void) { - response { response in - completionHandler(response) + func responseWith(completionHandler: @escaping (RxAlamofireResponse) -> Void) { + response { response in + completionHandler(response) + } } - } } extension Reactive where Base: SessionManager { - // MARK: Generic request convenience - - /** - Creates an observable of the DataRequest. - - - parameter createRequest: A function used to create a `Request` using a `Manager` - - - returns: A generic observable of created data request - */ - func request(_ createRequest: @escaping (SessionManager) throws -> R) -> Observable { - return Observable.create { observer -> Disposable in - let request: R - do { - request = try createRequest(self.base) - observer.on(.next(request)) - request.responseWith(completionHandler: { response in - if let error = response.error { - observer.on(.error(error)) - } else { - observer.on(.completed) - } - }) - - if !self.base.startRequestsImmediately { - request.resume() - } - - return Disposables.create { - request.cancel() + // MARK: Generic request convenience + + /** + Creates an observable of the DataRequest. + + - parameter createRequest: A function used to create a `Request` using a `Manager` + + - returns: A generic observable of created data request + */ + func request(_ createRequest: @escaping (SessionManager) throws -> R) -> Single { + return .create { (singleEventListener) in + do { + let request = try createRequest(self.base) + request.responseWith(completionHandler: { (response) in + if let error = response.error { + singleEventListener(.error(error)) + } + else { + singleEventListener(.success(request)) + } + }) + if !self.base.startRequestsImmediately { + request.resume() + } + return Disposables.create { + request.cancel() + } + } + catch { + singleEventListener(.error(error)) + return Disposables.create() + } } - } catch { - observer.on(.error(error)) - return Disposables.create() - } } - } - - /** - Creates an observable of the `Request`. - - - parameter method: Alamofire method object - - parameter url: An object adopting `URLConvertible` - - parameter parameters: A dictionary containing all necessary options - - parameter encoding: The kind of encoding used to process parameters - - parameter header: A dictionary containing all the additional headers - - - returns: An observable of the `Request` - */ - public func request(_ method: Alamofire.HTTPMethod, - _ url: URLConvertible, - parameters: [String: Any]? = nil, - encoding: ParameterEncoding = URLEncoding.default, - headers: [String: String]? = nil) - -> Observable { - return request { manager in - manager.request(url, - method: method, - parameters: parameters, - encoding: encoding, - headers: headers) + + /** + Creates an observable of the `Request`. + + - parameter method: Alamofire method object + - parameter url: An object adopting `URLConvertible` + - parameter parameters: A dictionary containing all necessary options + - parameter encoding: The kind of encoding used to process parameters + - parameter header: A dictionary containing all the additional headers + + - returns: An observable of the `Request` + */ + public func request(_ method: Alamofire.HTTPMethod, + _ url: URLConvertible, + parameters: [String: Any]? = nil, + encoding: ParameterEncoding = URLEncoding.default, + headers: [String: String]? = nil) + -> Single { + return request { manager in + manager.request(url, + method: method, + parameters: parameters, + encoding: encoding, + headers: headers) + } } - } - - /** - Creates an observable of the `Request`. - - - parameter URLRequest: An object adopting `URLRequestConvertible` - - parameter parameters: A dictionary containing all necessary options - - parameter encoding: The kind of encoding used to process parameters - - parameter header: A dictionary containing all the additional headers - - - returns: An observable of the `Request` - */ - public func request(urlRequest: URLRequestConvertible) - -> Observable { - return request { manager in - manager.request(urlRequest) + + /** + Creates an observable of the `Request`. + + - parameter URLRequest: An object adopting `URLRequestConvertible` + - parameter parameters: A dictionary containing all necessary options + - parameter encoding: The kind of encoding used to process parameters + - parameter header: A dictionary containing all the additional headers + + - returns: An observable of the `Request` + */ + public func request(urlRequest: URLRequestConvertible) + -> Single { + return request { manager in + manager.request(urlRequest) + } } - } - - // MARK: data - - /** - Creates an observable of the data. - - - parameter url: An object adopting `URLConvertible` - - parameter parameters: A dictionary containing all necessary options - - parameter encoding: The kind of encoding used to process parameters - - parameter header: A dictionary containing all the additional headers - - - returns: An observable of the tuple `(NSHTTPURLResponse, NSData)` - */ - public func responseData(_ method: Alamofire.HTTPMethod, - _ url: URLConvertible, - parameters: [String: Any]? = nil, - encoding: ParameterEncoding = URLEncoding.default, - headers: [String: String]? = nil) - -> Observable<(HTTPURLResponse, Data)> { - return request(method, - url, - parameters: parameters, - encoding: encoding, - headers: headers).flatMap { $0.rx.responseData() } - } - - /** - Creates an observable of the data. - - - parameter URLRequest: An object adopting `URLRequestConvertible` - - parameter parameters: A dictionary containing all necessary options - - parameter encoding: The kind of encoding used to process parameters - - parameter header: A dictionary containing all the additional headers - - - returns: An observable of `NSData` - */ - public func data(_ method: Alamofire.HTTPMethod, - _ url: URLConvertible, - parameters: [String: Any]? = nil, - encoding: ParameterEncoding = URLEncoding.default, - headers: [String: String]? = nil) - -> Observable { - return request(method, - url, - parameters: parameters, - encoding: encoding, - headers: headers).flatMap { $0.rx.data() } - } - - // MARK: string - - /** - Creates an observable of the tuple `(NSHTTPURLResponse, String)`. - - - parameter url: An object adopting `URLRequestConvertible` - - parameter parameters: A dictionary containing all necessary options - - parameter encoding: The kind of encoding used to process parameters - - parameter header: A dictionary containing all the additional headers - - - returns: An observable of the tuple `(NSHTTPURLResponse, String)` - */ - public func responseString(_ method: Alamofire.HTTPMethod, + + // MARK: data + + /** + Creates an observable of the data. + + - parameter url: An object adopting `URLConvertible` + - parameter parameters: A dictionary containing all necessary options + - parameter encoding: The kind of encoding used to process parameters + - parameter header: A dictionary containing all the additional headers + + - returns: An observable of the tuple `(NSHTTPURLResponse, NSData)` + */ + public func responseData(_ method: Alamofire.HTTPMethod, _ url: URLConvertible, parameters: [String: Any]? = nil, encoding: ParameterEncoding = URLEncoding.default, headers: [String: String]? = nil) - -> Observable<(HTTPURLResponse, String)> { - return request(method, - url, - parameters: parameters, - encoding: encoding, - headers: headers).flatMap { $0.rx.responseString() } - } - - /** - Creates an observable of the data encoded as String. - - - parameter url: An object adopting `URLConvertible` - - parameter parameters: A dictionary containing all necessary options - - parameter encoding: The kind of encoding used to process parameters - - parameter header: A dictionary containing all the additional headers - - - returns: An observable of `String` - */ - public func string(_ method: Alamofire.HTTPMethod, + -> Single<(HTTPURLResponse, Data)> { + return request(method, + url, + parameters: parameters, + encoding: encoding, + headers: headers).flatMap { $0.rx.responseData() } + } + + /** + Creates an observable of the data. + + - parameter URLRequest: An object adopting `URLRequestConvertible` + - parameter parameters: A dictionary containing all necessary options + - parameter encoding: The kind of encoding used to process parameters + - parameter header: A dictionary containing all the additional headers + + - returns: An observable of `NSData` + */ + public func data(_ method: Alamofire.HTTPMethod, _ url: URLConvertible, parameters: [String: Any]? = nil, encoding: ParameterEncoding = URLEncoding.default, headers: [String: String]? = nil) - -> Observable { - return request(method, - url, - parameters: parameters, - encoding: encoding, - headers: headers) - .flatMap { (request) -> Observable in - request.rx.string() - } - } - - // MARK: JSON - - /** - Creates an observable of the data decoded from JSON and processed as tuple `(NSHTTPURLResponse, AnyObject)`. - - - parameter url: An object adopting `URLRequestConvertible` - - parameter parameters: A dictionary containing all necessary options - - parameter encoding: The kind of encoding used to process parameters - - parameter header: A dictionary containing all the additional headers - - - returns: An observable of the tuple `(NSHTTPURLResponse, AnyObject)` - */ - public func responseJSON(_ method: Alamofire.HTTPMethod, - _ url: URLConvertible, - parameters: [String: Any]? = nil, - encoding: ParameterEncoding = URLEncoding.default, - headers: [String: String]? = nil) - -> Observable<(HTTPURLResponse, Any)> { - return request(method, - url, - parameters: parameters, - encoding: encoding, - headers: headers).flatMap { $0.rx.responseJSON() } - } - - /** - Creates an observable of the data decoded from JSON and processed as `AnyObject`. - - - parameter URLRequest: An object adopting `URLRequestConvertible` - - parameter parameters: A dictionary containing all necessary options - - parameter encoding: The kind of encoding used to process parameters - - parameter header: A dictionary containing all the additional headers - - - returns: An observable of `AnyObject` - */ - public func json(_ method: Alamofire.HTTPMethod, - _ url: URLConvertible, - parameters: [String: Any]? = nil, - encoding: ParameterEncoding = URLEncoding.default, - headers: [String: String]? = nil) - -> Observable { - return request(method, - url, - parameters: parameters, - encoding: encoding, - headers: headers).flatMap { $0.rx.json() } - } - - // MARK: Upload - - /** - Returns an observable of a request using the shared manager instance to upload a specific file to a specified URL. - The request is started immediately. - - - parameter urlRequest: The request object to start the upload. - - paramenter file: An instance of NSURL holding the information of the local file. - - returns: The observable of `AnyObject` for the created request. - */ - public func upload(_ file: URL, urlRequest: URLRequestConvertible) -> Observable { - return request { manager in - manager.upload(file, with: urlRequest) + -> Single { + return request(method, + url, + parameters: parameters, + encoding: encoding, + headers: headers).flatMap { $0.rx.data() } } - } - - /** - Returns an observable of a request using the shared manager instance to upload any data to a specified URL. - The request is started immediately. - - - parameter urlRequest: The request object to start the upload. - - paramenter data: An instance of Data holdint the data to upload. - - returns: The observable of `UploadRequest` for the created request. - */ - public func upload(_ data: Data, urlRequest: URLRequestConvertible) -> Observable { - return request { manager in - manager.upload(data, with: urlRequest) + + // MARK: string + + /** + Creates an observable of the tuple `(NSHTTPURLResponse, String)`. + + - parameter url: An object adopting `URLRequestConvertible` + - parameter parameters: A dictionary containing all necessary options + - parameter encoding: The kind of encoding used to process parameters + - parameter header: A dictionary containing all the additional headers + + - returns: An observable of the tuple `(NSHTTPURLResponse, String)` + */ + public func responseString(_ method: Alamofire.HTTPMethod, + _ url: URLConvertible, + parameters: [String: Any]? = nil, + encoding: ParameterEncoding = URLEncoding.default, + headers: [String: String]? = nil) + -> Single<(HTTPURLResponse, String)> { + return request(method, + url, + parameters: parameters, + encoding: encoding, + headers: headers).flatMap { $0.rx.responseString() } } - } - - /** - Returns an observable of a request using the shared manager instance to upload any stream to a specified URL. - The request is started immediately. - - - parameter urlRequest: The request object to start the upload. - - paramenter stream: The stream to upload. - - returns: The observable of `(NSData?, RxProgress)` for the created upload request. - */ - public func upload(_ stream: InputStream, - urlRequest: URLRequestConvertible) -> Observable { - return request { manager in - manager.upload(stream, with: urlRequest) + + /** + Creates an observable of the data encoded as String. + + - parameter url: An object adopting `URLConvertible` + - parameter parameters: A dictionary containing all necessary options + - parameter encoding: The kind of encoding used to process parameters + - parameter header: A dictionary containing all the additional headers + + - returns: An observable of `String` + */ + public func string(_ method: Alamofire.HTTPMethod, + _ url: URLConvertible, + parameters: [String: Any]? = nil, + encoding: ParameterEncoding = URLEncoding.default, + headers: [String: String]? = nil) + -> Single { + return request(method, + url, + parameters: parameters, + encoding: encoding, + headers: headers) + .flatMap { (request) -> Single in + request.rx.string() + } } - } - - // MARK: Download - - /** - Creates a download request using the shared manager instance for the specified URL request. - - parameter urlRequest: The URL request. - - parameter destination: The closure used to determine the destination of the downloaded file. - - returns: The observable of `(NSData?, RxProgress)` for the created download request. - */ - public func download(_ urlRequest: URLRequestConvertible, - to destination: @escaping DownloadRequest.DownloadFileDestination) -> Observable { - return request { manager in - manager.download(urlRequest, to: destination) + + // MARK: JSON + + /** + Creates an observable of the data decoded from JSON and processed as tuple `(NSHTTPURLResponse, AnyObject)`. + + - parameter url: An object adopting `URLRequestConvertible` + - parameter parameters: A dictionary containing all necessary options + - parameter encoding: The kind of encoding used to process parameters + - parameter header: A dictionary containing all the additional headers + + - returns: An observable of the tuple `(NSHTTPURLResponse, AnyObject)` + */ + public func responseJSON(_ method: Alamofire.HTTPMethod, + _ url: URLConvertible, + parameters: [String: Any]? = nil, + encoding: ParameterEncoding = URLEncoding.default, + headers: [String: String]? = nil) + -> Single<(HTTPURLResponse, Any)> { + return request(method, + url, + parameters: parameters, + encoding: encoding, + headers: headers).flatMap { $0.rx.responseJSON() } } - } - - /** - Creates a request using the shared manager instance for downloading with a resume data produced from a - previous request cancellation. - - - parameter resumeData: The resume data. This is an opaque data blob produced by `NSURLSessionDownloadTask` - when a task is cancelled. See `NSURLSession -downloadTaskWithResumeData:` for additional - information. - - parameter destination: The closure used to determine the destination of the downloaded file. - - returns: The observable of `(NSData?, RxProgress)` for the created download request. - */ - public func download(resumeData: Data, - to destination: @escaping DownloadRequest.DownloadFileDestination) -> Observable { - return request { manager in - manager.download(resumingWith: resumeData, to: destination) + + /** + Creates an observable of the data decoded from JSON and processed as `AnyObject`. + + - parameter URLRequest: An object adopting `URLRequestConvertible` + - parameter parameters: A dictionary containing all necessary options + - parameter encoding: The kind of encoding used to process parameters + - parameter header: A dictionary containing all the additional headers + + - returns: An observable of `AnyObject` + */ + public func json(_ method: Alamofire.HTTPMethod, + _ url: URLConvertible, + parameters: [String: Any]? = nil, + encoding: ParameterEncoding = URLEncoding.default, + headers: [String: String]? = nil) + -> Single { + return request(method, + url, + parameters: parameters, + encoding: encoding, + headers: headers).flatMap { $0.rx.json() } + } + + // MARK: Upload + + /** + Returns an observable of a request using the shared manager instance to upload a specific file to a specified URL. + The request is started immediately. + + - parameter urlRequest: The request object to start the upload. + - paramenter file: An instance of NSURL holding the information of the local file. + - returns: The observable of `AnyObject` for the created request. + */ + public func upload(_ file: URL, urlRequest: URLRequestConvertible) -> Single { + return request { manager in + manager.upload(file, with: urlRequest) + } + } + + /** + Returns an observable of a request using the shared manager instance to upload any data to a specified URL. + The request is started immediately. + + - parameter urlRequest: The request object to start the upload. + - paramenter data: An instance of Data holdint the data to upload. + - returns: The observable of `UploadRequest` for the created request. + */ + public func upload(_ data: Data, urlRequest: URLRequestConvertible) -> Single { + return request { manager in + manager.upload(data, with: urlRequest) + } + } + + /** + Returns an observable of a request using the shared manager instance to upload any stream to a specified URL. + The request is started immediately. + + - parameter urlRequest: The request object to start the upload. + - paramenter stream: The stream to upload. + - returns: The observable of `(NSData?, RxProgress)` for the created upload request. + */ + public func upload(_ stream: InputStream, + urlRequest: URLRequestConvertible) -> Single { + return request { manager in + manager.upload(stream, with: urlRequest) + } + } + + // MARK: Download + + /** + Creates a download request using the shared manager instance for the specified URL request. + - parameter urlRequest: The URL request. + - parameter destination: The closure used to determine the destination of the downloaded file. + - returns: The observable of `(NSData?, RxProgress)` for the created download request. + */ + public func download(_ urlRequest: URLRequestConvertible, + to destination: @escaping DownloadRequest.DownloadFileDestination) -> Single { + return request { manager in + manager.download(urlRequest, to: destination) + } + } + + /** + Creates a request using the shared manager instance for downloading with a resume data produced from a + previous request cancellation. + + - parameter resumeData: The resume data. This is an opaque data blob produced by `NSURLSessionDownloadTask` + when a task is cancelled. See `NSURLSession -downloadTaskWithResumeData:` for additional + information. + - parameter destination: The closure used to determine the destination of the downloaded file. + - returns: The observable of `(NSData?, RxProgress)` for the created download request. + */ + public func download(resumeData: Data, + to destination: @escaping DownloadRequest.DownloadFileDestination) -> Single { + return request { manager in + manager.download(resumingWith: resumeData, to: destination) + } } - } } // MARK: Request - Common Response Handlers extension ObservableType where Element == DataRequest { - public func responseJSON() -> Observable> { - return flatMap { $0.rx.responseJSON() } - } - - public func json(options: JSONSerialization.ReadingOptions = .allowFragments) -> Observable { - return flatMap { $0.rx.json(options: options) } - } - - public func responseString(encoding: String.Encoding? = nil) -> Observable<(HTTPURLResponse, String)> { - return flatMap { $0.rx.responseString(encoding: encoding) } - } - - public func string(encoding: String.Encoding? = nil) -> Observable { - return flatMap { $0.rx.string(encoding: encoding) } - } - - public func responseData() -> Observable<(HTTPURLResponse, Data)> { - return flatMap { $0.rx.responseData() } - } - - public func data() -> Observable { - return flatMap { $0.rx.data() } - } - - public func responsePropertyList(options: PropertyListSerialization.ReadOptions = PropertyListSerialization.ReadOptions()) -> Observable<(HTTPURLResponse, Any)> { - return flatMap { $0.rx.responsePropertyList(options: options) } - } - - public func propertyList(options: PropertyListSerialization.ReadOptions = PropertyListSerialization.ReadOptions()) -> Observable { - return flatMap { $0.rx.propertyList(options: options) } - } - - public func progress() -> Observable { - return flatMap { $0.rx.progress() } - } + public func responseJSON() -> Observable> { + return flatMap { $0.rx.responseJSON() } + } + + public func json(options: JSONSerialization.ReadingOptions = .allowFragments) -> Observable { + return flatMap { $0.rx.json(options: options) } + } + + public func responseString(encoding: String.Encoding? = nil) -> Observable<(HTTPURLResponse, String)> { + return flatMap { $0.rx.responseString(encoding: encoding) } + } + + public func string(encoding: String.Encoding? = nil) -> Observable { + return flatMap { $0.rx.string(encoding: encoding) } + } + + public func responseData() -> Observable<(HTTPURLResponse, Data)> { + return flatMap { $0.rx.responseData() } + } + + public func data() -> Observable { + return flatMap { $0.rx.data() } + } + + public func responsePropertyList(options: PropertyListSerialization.ReadOptions = PropertyListSerialization.ReadOptions()) -> Observable<(HTTPURLResponse, Any)> { + return flatMap { $0.rx.responsePropertyList(options: options) } + } + + public func propertyList(options: PropertyListSerialization.ReadOptions = PropertyListSerialization.ReadOptions()) -> Observable { + return flatMap { $0.rx.propertyList(options: options) } + } + + public func progress() -> Observable { + return flatMap { $0.rx.progress() } + } } extension ObservableType where Element: DownloadRequest { - public func response() -> Observable { - return flatMap { $0.rx.response() } - } + public func response() -> Observable { + return flatMap { $0.rx.response() } + } - public func responseSerialized( - queue: DispatchQueue? = nil, - responseSerializer: Serializer - ) - -> Observable> - { - return flatMap { $0.rx.responseSerialized(queue: queue, responseSerializer: responseSerializer) } - } + public func responseSerialized( + queue: DispatchQueue? = nil, + responseSerializer: Serializer + ) + -> Observable> + { + return flatMap { $0.rx.responseSerialized(queue: queue, responseSerializer: responseSerializer) } + } + + public func responseResult( + queue: DispatchQueue? = nil, + responseSerializer: Serializer + ) + -> Observable + { + return flatMap { $0.rx.responseResult(queue: queue, responseSerializer: responseSerializer) } + } - public func responseResult( - queue: DispatchQueue? = nil, - responseSerializer: Serializer - ) - -> Observable - { - return flatMap { $0.rx.responseResult(queue: queue, responseSerializer: responseSerializer) } - } - } // MARK: Request - Validation extension ObservableType where Element == DataRequest { - public func validate(statusCode: S) -> Observable where S.Element == Int { - return map { $0.validate(statusCode: statusCode) } - } - - public func validate() -> Observable { - return map { $0.validate() } - } - - public func validate(contentType acceptableContentTypes: S) -> Observable where S.Iterator.Element == String { - return map { $0.validate(contentType: acceptableContentTypes) } - } - - public func validate(_ validation: @escaping DataRequest.Validation) -> Observable { - return map { $0.validate(validation) } - } + public func validate(statusCode: S) -> Observable where S.Element == Int { + return map { $0.validate(statusCode: statusCode) } + } + + public func validate() -> Observable { + return map { $0.validate() } + } + + public func validate(contentType acceptableContentTypes: S) -> Observable where S.Iterator.Element == String { + return map { $0.validate(contentType: acceptableContentTypes) } + } + + public func validate(_ validation: @escaping DataRequest.Validation) -> Observable { + return map { $0.validate(validation) } + } } extension Request: ReactiveCompatible {} extension Reactive where Base: DataRequest { - // MARK: Defaults - - /// - returns: A validated request based on the status code - func validateSuccessfulResponse() -> DataRequest { - return base.validate(statusCode: 200..<300) - } - - /** - Transform a request into an observable of the response and serialized object. - - - parameter queue: The dispatch queue to use. - - parameter responseSerializer: The the serializer. - - returns: The observable of `(NSHTTPURLResponse, T.SerializedObject)` for the created download request. - */ - public func responseResult(queue: DispatchQueue? = nil, - responseSerializer: T) - -> Observable<(HTTPURLResponse, T.SerializedObject)> { - return Observable.create { observer in - let dataRequest = self.base - .response(queue: queue, responseSerializer: responseSerializer) { (packedResponse) -> Void in - switch packedResponse.result { - case let .success(result): - if let httpResponse = packedResponse.response { - observer.on(.next((httpResponse, result))) - observer.on(.completed) - } else { - observer.on(.error(RxAlamofireUnknownError)) + // MARK: Defaults + + /// - returns: A validated request based on the status code + func validateSuccessfulResponse() -> DataRequest { + return base.validate(statusCode: 200..<300) + } + + /** + Transform a request into an observable of the response and serialized object. + + - parameter queue: The dispatch queue to use. + - parameter responseSerializer: The the serializer. + - returns: The observable of `(NSHTTPURLResponse, T.SerializedObject)` for the created download request. + */ + public func responseResult(queue: DispatchQueue? = nil, + responseSerializer: T) + -> Single<(HTTPURLResponse, T.SerializedObject)> { + return .create { (singleEventListener) in + let dataRequest = self.base + .response(queue: queue, responseSerializer: responseSerializer) { (packedResponse) -> Void in + switch packedResponse.result { + case let .success(result): + if let httpResponse = packedResponse.response { + singleEventListener(.success((httpResponse, result))) + } else { + singleEventListener(.error(RxAlamofireUnknownError)) + } + case let .failure(error): + singleEventListener(.error(error)) + } + } + return Disposables.create { + dataRequest.cancel() + } } - case let .failure(error): - observer.on(.error(error as Error)) - } - } - return Disposables.create { - dataRequest.cancel() - } } - } - - public func responseJSON() -> Observable> { - return Observable.create { observer in - let request = self.base - - request.responseJSON { response in - if let error = response.result.error { - observer.on(.error(error)) - } else { - observer.on(.next(response)) - observer.on(.completed) + + public func responseJSON() -> Single> { + return .create { (singleEventListener) in + let request = self.base + + request.responseJSON { response in + if let error = response.result.error { + singleEventListener(.error(error)) + } else { + singleEventListener(.success(response)) + } + } + + return Disposables.create { + request.cancel() + } } - } - - return Disposables.create { - request.cancel() - } } - } - - /** - Transform a request into an observable of the serialized object. - - - parameter queue: The dispatch queue to use. - - parameter responseSerializer: The the serializer. - - returns: The observable of `T.SerializedObject` for the created download request. - */ - public func result(queue: DispatchQueue? = nil, - responseSerializer: T) - -> Observable { - return Observable.create { observer in - let dataRequest = self.validateSuccessfulResponse() - .response(queue: queue, responseSerializer: responseSerializer) { (packedResponse) -> Void in - switch packedResponse.result { - case let .success(result): - if let _ = packedResponse.response { - observer.on(.next(result)) - observer.on(.completed) - } else { - observer.on(.error(RxAlamofireUnknownError)) + + /** + Transform a request into an observable of the serialized object. + + - parameter queue: The dispatch queue to use. + - parameter responseSerializer: The the serializer. + - returns: The observable of `T.SerializedObject` for the created download request. + */ + public func result(queue: DispatchQueue? = nil, + responseSerializer: T) + -> Single { + return .create { (singleEventListener) in + let dataRequest = self.validateSuccessfulResponse() + .response(queue: queue, responseSerializer: responseSerializer) { (packedResponse) -> Void in + switch packedResponse.result { + case let .success(result): + if let _ = packedResponse.response { + singleEventListener(.success(result)) + } else { + singleEventListener(.error(RxAlamofireUnknownError)) + } + case let .failure(error): + singleEventListener(.error(error)) + } + } + return Disposables.create { + dataRequest.cancel() + } } - case let .failure(error): - observer.on(.error(error as Error)) - } - } - return Disposables.create { - dataRequest.cancel() - } } - } - - /** - Returns an `Observable` of NSData for the current request. - - - parameter cancelOnDispose: Indicates if the request has to be canceled when the observer is disposed, **default:** `false` - - - returns: An instance of `Observable` - */ - public func responseData() -> Observable<(HTTPURLResponse, Data)> { - return responseResult(responseSerializer: DataRequest.dataResponseSerializer()) - } - - public func data() -> Observable { - return result(responseSerializer: DataRequest.dataResponseSerializer()) - } - - /** - Returns an `Observable` of a String for the current request - - - parameter encoding: Type of the string encoding, **default:** `nil` - - - returns: An instance of `Observable` - */ - public func responseString(encoding: String.Encoding? = nil) -> Observable<(HTTPURLResponse, String)> { - return responseResult(responseSerializer: Base.stringResponseSerializer(encoding: encoding)) - } - - public func string(encoding: String.Encoding? = nil) -> Observable { - return result(responseSerializer: Base.stringResponseSerializer(encoding: encoding)) - } - - /** - Returns an `Observable` of a serialized JSON for the current request. - - - parameter options: Reading options for JSON decoding process, **default:** `.AllowFragments` - - - returns: An instance of `Observable` - */ - public func responseJSON(options: JSONSerialization.ReadingOptions = .allowFragments) -> Observable<(HTTPURLResponse, Any)> { - return responseResult(responseSerializer: Base.jsonResponseSerializer(options: options)) - } - - /** - Returns an `Observable` of a serialized JSON for the current request. - - - parameter options: Reading options for JSON decoding process, **default:** `.AllowFragments` - - - returns: An instance of `Observable` - */ - public func json(options: JSONSerialization.ReadingOptions = .allowFragments) -> Observable { - return result(responseSerializer: Base.jsonResponseSerializer(options: options)) - } - - /** - Returns and `Observable` of a serialized property list for the current request. - - - parameter options: Property list reading options, **default:** `NSPropertyListReadOptions()` - - - returns: An instance of `Observable` - */ - public func responsePropertyList(options: PropertyListSerialization.ReadOptions = PropertyListSerialization.ReadOptions()) -> Observable<(HTTPURLResponse, Any)> { - return responseResult(responseSerializer: Base.propertyListResponseSerializer(options: options)) - } - - public func propertyList(options: PropertyListSerialization.ReadOptions = PropertyListSerialization.ReadOptions()) -> Observable { - return result(responseSerializer: Base.propertyListResponseSerializer(options: options)) - } + + /** + Returns an `Observable` of NSData for the current request. + + - parameter cancelOnDispose: Indicates if the request has to be canceled when the observer is disposed, **default:** `false` + + - returns: An instance of `Single` + */ + public func responseData() -> Single<(HTTPURLResponse, Data)> { + return responseResult(responseSerializer: DataRequest.dataResponseSerializer()) + } + + public func data() -> Single { + return result(responseSerializer: DataRequest.dataResponseSerializer()) + } + + /** + Returns an `Observable` of a String for the current request + + - parameter encoding: Type of the string encoding, **default:** `nil` + + - returns: An instance of `Single` + */ + public func responseString(encoding: String.Encoding? = nil) -> Single<(HTTPURLResponse, String)> { + return responseResult(responseSerializer: Base.stringResponseSerializer(encoding: encoding)) + } + + public func string(encoding: String.Encoding? = nil) -> Single { + return result(responseSerializer: Base.stringResponseSerializer(encoding: encoding)) + } + + /** + Returns an `Observable` of a serialized JSON for the current request. + + - parameter options: Reading options for JSON decoding process, **default:** `.AllowFragments` + + - returns: An instance of `Single` + */ + public func responseJSON(options: JSONSerialization.ReadingOptions = .allowFragments) -> Single<(HTTPURLResponse, Any)> { + return responseResult(responseSerializer: Base.jsonResponseSerializer(options: options)) + } + + /** + Returns an `Observable` of a serialized JSON for the current request. + + - parameter options: Reading options for JSON decoding process, **default:** `.AllowFragments` + + - returns: An instance of `Single` + */ + public func json(options: JSONSerialization.ReadingOptions = .allowFragments) -> Single { + return result(responseSerializer: Base.jsonResponseSerializer(options: options)) + } + + /** + Returns and `Observable` of a serialized property list for the current request. + + - parameter options: Property list reading options, **default:** `NSPropertyListReadOptions()` + + - returns: An instance of `Single` + */ + public func responsePropertyList(options: PropertyListSerialization.ReadOptions = PropertyListSerialization.ReadOptions()) -> Single<(HTTPURLResponse, Any)> { + return responseResult(responseSerializer: Base.propertyListResponseSerializer(options: options)) + } + + public func propertyList(options: PropertyListSerialization.ReadOptions = PropertyListSerialization.ReadOptions()) -> Single { + return result(responseSerializer: Base.propertyListResponseSerializer(options: options)) + } } // MARK: Reactive + DownloadRequest extension Reactive where Base: DownloadRequest { - public func response() -> Observable { - return Observable.create { observer in - let request = self.base.response { response in - if let error = response.error { - observer.onError(error) - } else { - observer.onNext(response) - observer.onCompleted() + public func response() -> Single { + return .create { (singleEventListener) in + let request = self.base.response { (response) in + if let error = response.error { + singleEventListener(.error(error)) + } else { + singleEventListener(.success(response)) + } + } + return Disposables.create(with: request.cancel) } - } - return Disposables.create(with: request.cancel) } - } - public func responseSerialized( - queue: DispatchQueue? = nil, - responseSerializer: Serializer - ) - -> Observable> - { - return Observable.create { observer in - let request = self.base.response( - queue: queue, - responseSerializer: responseSerializer - ) { response in - if let error = response.error { - observer.onError(error) - } else { - observer.onNext(response) - observer.onCompleted() + public func responseSerialized( + queue: DispatchQueue? = nil, + responseSerializer: Serializer + ) + -> Single> + { + return .create { (singleEventListener) in + let request = self.base.response( + queue: queue, + responseSerializer: responseSerializer + ) { response in + if let error = response.error { + singleEventListener(.error(error)) + } else { + singleEventListener(.success(response)) + } + } + return Disposables.create(with: request.cancel) } - } - return Disposables.create(with: request.cancel) } - } - public func responseResult( - queue: DispatchQueue? = nil, - responseSerializer: Serializer - ) - -> Observable - { - return responseSerialized(queue: queue, responseSerializer: responseSerializer) - .map { - guard let value = $0.value else { - throw RxAlamofireUnknownError + public func responseResult( + queue: DispatchQueue? = nil, + responseSerializer: Serializer + ) + -> Single + { + return responseSerialized(queue: queue, responseSerializer: responseSerializer) + .map { + guard let value = $0.value else { + throw RxAlamofireUnknownError + } + return value } - return value - } - } + } } extension Reactive where Base: Request { - // MARK: Request - Upload and download progress - - /** - Returns an `Observable` for the current progress status. - - Parameters on observed tuple: - - 1. bytes written so far. - 1. total bytes to write. - - - returns: An instance of `Observable` - */ - public func progress() -> Observable { - return Observable.create { observer in - let handler: Request.ProgressHandler = { progress in - let rxProgress = RxProgress(bytesWritten: progress.completedUnitCount, - totalBytes: progress.totalUnitCount) - observer.on(.next(rxProgress)) - - if rxProgress.bytesWritten >= rxProgress.totalBytes { - observer.on(.completed) + // MARK: Request - Upload and download progress + + /** + Returns an `Observable` for the current progress status. + + Parameters on observed tuple: + + 1. bytes written so far. + 1. total bytes to write. + + - returns: An instance of `Observable` + */ + public func progress() -> Observable { + return Observable.create { observer in + let handler: Request.ProgressHandler = { progress in + let rxProgress = RxProgress(bytesWritten: progress.completedUnitCount, + totalBytes: progress.totalUnitCount) + observer.on(.next(rxProgress)) + + if rxProgress.bytesWritten >= rxProgress.totalBytes { + observer.on(.completed) + } + } + + // Try in following order: + // - UploadRequest (Inherits from DataRequest, so we test the discrete case first) + // - DownloadRequest + // - DataRequest + if let uploadReq = self.base as? UploadRequest { + uploadReq.uploadProgress(closure: handler) + } else if let downloadReq = self.base as? DownloadRequest { + downloadReq.downloadProgress(closure: handler) + } else if let dataReq = self.base as? DataRequest { + dataReq.downloadProgress(closure: handler) + } + + return Disposables.create() } - } - - // Try in following order: - // - UploadRequest (Inherits from DataRequest, so we test the discrete case first) - // - DownloadRequest - // - DataRequest - if let uploadReq = self.base as? UploadRequest { - uploadReq.uploadProgress(closure: handler) - } else if let downloadReq = self.base as? DownloadRequest { - downloadReq.downloadProgress(closure: handler) - } else if let dataReq = self.base as? DataRequest { - dataReq.downloadProgress(closure: handler) - } - - return Disposables.create() + // warm up a bit :) + .startWith(RxProgress(bytesWritten: 0, totalBytes: 0)) } - // warm up a bit :) - .startWith(RxProgress(bytesWritten: 0, totalBytes: 0)) - } } // MARK: RxProgress public struct RxProgress { - public let bytesWritten: Int64 - public let totalBytes: Int64 - - public init(bytesWritten: Int64, totalBytes: Int64) { - self.bytesWritten = bytesWritten - self.totalBytes = totalBytes - } + public let bytesWritten: Int64 + public let totalBytes: Int64 + + public init(bytesWritten: Int64, totalBytes: Int64) { + self.bytesWritten = bytesWritten + self.totalBytes = totalBytes + } } extension RxProgress { - public var bytesRemaining: Int64 { - return totalBytes - bytesWritten - } - - public var completed: Float { - if totalBytes > 0 { - return Float(bytesWritten) / Float(totalBytes) - } else { - return 0 + public var bytesRemaining: Int64 { + return totalBytes - bytesWritten + } + + public var completed: Float { + if totalBytes > 0 { + return Float(bytesWritten) / Float(totalBytes) + } else { + return 0 + } } - } } extension RxProgress: Equatable {} public func ==(lhs: RxProgress, rhs: RxProgress) -> Bool { - return lhs.bytesWritten == rhs.bytesWritten && - lhs.totalBytes == rhs.totalBytes + return lhs.bytesWritten == rhs.bytesWritten && + lhs.totalBytes == rhs.totalBytes }