提交 5c586a33 编写于 作者: C Christian Noon

Merge pull request #593 from Alamofire/feature/response_generics

......@@ -134,56 +134,6 @@ public class Request {
return self
}
// MARK: - Response
/**
A closure used by response handlers that takes a request, response, and data and returns a serialized object and any error that occured in the process.
*/
public typealias Serializer = (NSURLRequest, NSHTTPURLResponse?, NSData?) -> (AnyObject?, NSError?)
/**
Creates a response serializer that returns the associated data as-is.
:returns: A data response serializer.
*/
public class func responseDataSerializer() -> Serializer {
return { request, response, data in
return (data, nil)
}
}
/**
Adds a handler to be called once the request has finished.
:param: completionHandler The code to be executed once the request has finished.
:returns: The request.
*/
public func response(completionHandler: (NSURLRequest, NSHTTPURLResponse?, AnyObject?, NSError?) -> Void) -> Self {
return response(serializer: Request.responseDataSerializer(), completionHandler: completionHandler)
}
/**
Adds a handler to be called once the request has finished.
:param: queue The queue on which the completion handler is dispatched.
:param: serializer The closure responsible for serializing the request, response, and data.
:param: completionHandler The code to be executed once the request has finished.
:returns: The request.
*/
public func response(queue: dispatch_queue_t? = nil, serializer: Serializer, completionHandler: (NSURLRequest, NSHTTPURLResponse?, AnyObject?, NSError?) -> Void) -> Self {
self.delegate.queue.addOperationWithBlock {
let (responseObject: AnyObject?, serializationError: NSError?) = serializer(self.request, self.response, self.delegate.data)
dispatch_async(queue ?? dispatch_get_main_queue()) {
completionHandler(self.request, self.response, responseObject, self.delegate.error ?? serializationError)
}
}
return self
}
// MARK: - State
/**
......
......@@ -22,9 +22,95 @@
import Foundation
// MARK: String
// MARK: - ResponseSerializer
/**
The type in which all response serializers must conform to in order to serialize a response.
*/
public protocol ResponseSerializer {
/// The type of serialized object to be created by this `ResponseSerializer`.
typealias SerializedObject
/// A closure used by response handlers that takes a request, response, and data and returns a serialized object and any error that occured in the process.
var serializeResponse: (NSURLRequest?, NSHTTPURLResponse?, NSData?) -> (SerializedObject?, NSError?) { get }
}
/**
A generic `ResponseSerializer` used to serialize a request, response, and data into a serialized object.
*/
public struct GenericResponseSerializer<T>: ResponseSerializer {
/// The type of serialized object to be created by this `ResponseSerializer`.
public typealias SerializedObject = T
/// A closure used by response handlers that takes a request, response, and data and returns a serialized object and any error that occured in the process.
public var serializeResponse: (NSURLRequest?, NSHTTPURLResponse?, NSData?) -> (SerializedObject?, NSError?)
}
// MARK: - Default
extension Request {
/**
Adds a handler to be called once the request has finished.
:param: queue The queue on which the completion handler is dispatched.
:param: responseSerializer The response serializer responsible for serializing the request, response, and data.
:param: completionHandler The code to be executed once the request has finished.
:returns: The request.
*/
public func response<T: ResponseSerializer, V where T.SerializedObject == V>(
queue: dispatch_queue_t? = nil,
responseSerializer: T,
completionHandler: (NSURLRequest, NSHTTPURLResponse?, V?, NSError?) -> Void)
-> Self
{
self.delegate.queue.addOperationWithBlock {
let result: V?
let error: NSError?
(result, error) = responseSerializer.serializeResponse(self.request, self.response, self.delegate.data)
dispatch_async(queue ?? dispatch_get_main_queue()) {
completionHandler(self.request, self.response, result, self.delegate.error ?? error)
}
}
return self
}
}
// MARK: - Data
extension Request {
/**
Creates a response serializer that returns the associated data as-is.
:returns: A data response serializer.
*/
public static func dataResponseSerializer() -> GenericResponseSerializer<NSData> {
return GenericResponseSerializer { request, response, data in
return (data, nil)
}
}
/**
Adds a handler to be called once the request has finished.
:param: completionHandler The code to be executed once the request has finished.
:returns: The request.
*/
public func response(completionHandler: (NSURLRequest, NSHTTPURLResponse?, NSData?, NSError?) -> Void) -> Self {
return response(responseSerializer: Request.dataResponseSerializer(), completionHandler: completionHandler)
}
}
// MARK: - String
extension Request {
/**
Creates a response serializer that returns a string initialized from the response data with the specified string encoding.
......@@ -32,8 +118,8 @@ extension Request {
:returns: A string response serializer.
*/
public class func stringResponseSerializer(var encoding: NSStringEncoding? = nil) -> Serializer {
return { _, response, data in
public static func stringResponseSerializer(var encoding: NSStringEncoding? = nil) -> GenericResponseSerializer<String> {
return GenericResponseSerializer { _, response, data in
if data == nil || data?.length == 0 {
return (nil, nil)
}
......@@ -42,7 +128,7 @@ extension Request {
encoding = CFStringConvertEncodingToNSStringEncoding(CFStringConvertIANACharSetNameToEncoding(encodingName))
}
let string = NSString(data: data!, encoding: encoding ?? NSISOLatin1StringEncoding)
let string = NSString(data: data!, encoding: encoding ?? NSISOLatin1StringEncoding) as? String
return (string, nil)
}
......@@ -56,16 +142,22 @@ extension Request {
:returns: The request.
*/
public func responseString(encoding: NSStringEncoding? = nil, completionHandler: (NSURLRequest, NSHTTPURLResponse?, String?, NSError?) -> Void) -> Self {
return response(serializer: Request.stringResponseSerializer(encoding: encoding)) { request, response, string, error in
completionHandler(request, response, string as? String, error)
}
public func responseString(
encoding: NSStringEncoding? = nil,
completionHandler: (NSURLRequest, NSHTTPURLResponse?, String?, NSError?) -> Void)
-> Self
{
return response(
responseSerializer: Request.stringResponseSerializer(encoding: encoding),
completionHandler: completionHandler
)
}
}
// MARK: - JSON
extension Request {
/**
Creates a response serializer that returns a JSON object constructed from the response data using `NSJSONSerialization` with the specified reading options.
......@@ -73,8 +165,8 @@ extension Request {
:returns: A JSON object response serializer.
*/
public class func JSONResponseSerializer(options: NSJSONReadingOptions = .AllowFragments) -> Serializer {
return { request, response, data in
public static func JSONResponseSerializer(options: NSJSONReadingOptions = .AllowFragments) -> GenericResponseSerializer<AnyObject> {
return GenericResponseSerializer { request, response, data in
if data == nil || data?.length == 0 {
return (nil, nil)
}
......@@ -94,16 +186,22 @@ extension Request {
:returns: The request.
*/
public func responseJSON(options: NSJSONReadingOptions = .AllowFragments, completionHandler: (NSURLRequest, NSHTTPURLResponse?, AnyObject?, NSError?) -> Void) -> Self {
return response(serializer: Request.JSONResponseSerializer(options: options)) { request, response, JSON, error in
completionHandler(request, response, JSON, error)
}
public func responseJSON(
options: NSJSONReadingOptions = .AllowFragments,
completionHandler: (NSURLRequest, NSHTTPURLResponse?, AnyObject?, NSError?) -> Void)
-> Self
{
return response(
responseSerializer: Request.JSONResponseSerializer(options: options),
completionHandler: completionHandler
)
}
}
// MARK: - Property List
extension Request {
/**
Creates a response serializer that returns an object constructed from the response data using `NSPropertyListSerialization` with the specified reading options.
......@@ -111,14 +209,19 @@ extension Request {
:returns: A property list object response serializer.
*/
public class func propertyListResponseSerializer(options: NSPropertyListReadOptions = 0) -> Serializer {
return { request, response, data in
public static func propertyListResponseSerializer(options: NSPropertyListReadOptions = 0) -> GenericResponseSerializer<AnyObject> {
return GenericResponseSerializer { request, response, data in
if data == nil || data?.length == 0 {
return (nil, nil)
}
var propertyListSerializationError: NSError?
let plist: AnyObject? = NSPropertyListSerialization.propertyListWithData(data!, options: options, format: nil, error: &propertyListSerializationError)
let plist: AnyObject? = NSPropertyListSerialization.propertyListWithData(
data!,
options: options,
format: nil,
error: &propertyListSerializationError
)
return (plist, propertyListSerializationError)
}
......@@ -132,9 +235,14 @@ extension Request {
:returns: The request.
*/
public func responsePropertyList(options: NSPropertyListReadOptions = 0, completionHandler: (NSURLRequest, NSHTTPURLResponse?, AnyObject?, NSError?) -> Void) -> Self {
return response(serializer: Request.propertyListResponseSerializer(options: options)) { request, response, plist, error in
completionHandler(request, response, plist, error)
}
public func responsePropertyList(
options: NSPropertyListReadOptions = 0,
completionHandler: (NSURLRequest, NSHTTPURLResponse?, AnyObject?, NSError?) -> Void)
-> Self
{
return response(
responseSerializer: Request.propertyListResponseSerializer(options: options),
completionHandler: completionHandler
)
}
}
......@@ -59,7 +59,7 @@ class BasicAuthenticationTestCase: AuthenticationTestCase {
var request: NSURLRequest?
var response: NSHTTPURLResponse?
var data: AnyObject?
var data: NSData?
var error: NSError?
// When
......@@ -90,7 +90,7 @@ class BasicAuthenticationTestCase: AuthenticationTestCase {
var request: NSURLRequest?
var response: NSHTTPURLResponse?
var data: AnyObject?
var data: NSData?
var error: NSError?
// When
......@@ -132,7 +132,7 @@ class HTTPDigestAuthenticationTestCase: AuthenticationTestCase {
var request: NSURLRequest?
var response: NSHTTPURLResponse?
var data: AnyObject?
var data: NSData?
var error: NSError?
// When
......@@ -163,7 +163,7 @@ class HTTPDigestAuthenticationTestCase: AuthenticationTestCase {
var request: NSURLRequest?
var response: NSHTTPURLResponse?
var data: AnyObject?
var data: NSData?
var error: NSError?
// When
......
......@@ -182,7 +182,7 @@ class CacheTestCase: BaseTestCase {
let request = self.manager.request(urlRequest)
request.response(
queue: queue,
serializer: Request.responseDataSerializer(),
responseSerializer: Request.dataResponseSerializer(),
completionHandler: { _, response, _, _ in
completion(request.request, response)
}
......
......@@ -154,7 +154,7 @@ class DownloadResponseTestCase: BaseTestCase {
var progressValues: [(completedUnitCount: Int64, totalUnitCount: Int64)] = []
var responseRequest: NSURLRequest?
var responseResponse: NSHTTPURLResponse?
var responseData: AnyObject?
var responseData: NSData?
var responseError: NSError?
// When
......
......@@ -80,18 +80,18 @@ class RequestResponseTestCase: BaseTestCase {
func testRequestResponse() {
// Given
let URLString = "http://httpbin.org/get"
let serializer = Alamofire.Request.stringResponseSerializer(encoding: NSUTF8StringEncoding)
let serializer = Request.stringResponseSerializer(encoding: NSUTF8StringEncoding)
let expectation = expectationWithDescription("GET request should succeed: \(URLString)")
var request: NSURLRequest?
var response: NSHTTPURLResponse?
var string: AnyObject?
var string: String?
var error: NSError?
// When
Alamofire.request(.GET, URLString, parameters: ["foo": "bar"])
.response(serializer: serializer) { responseRequest, responseResponse, responseString, responseError in
.response(responseSerializer: serializer) { responseRequest, responseResponse, responseString, responseError in
request = responseRequest
response = responseResponse
string = responseString
......@@ -120,7 +120,7 @@ class RequestResponseTestCase: BaseTestCase {
var progressValues: [(completedUnitCount: Int64, totalUnitCount: Int64)] = []
var responseRequest: NSURLRequest?
var responseResponse: NSHTTPURLResponse?
var responseData: AnyObject?
var responseData: NSData?
var responseError: NSError?
// When
......@@ -189,7 +189,7 @@ class RequestResponseTestCase: BaseTestCase {
var responseRequest: NSURLRequest?
var responseResponse: NSHTTPURLResponse?
var responseData: AnyObject?
var responseData: NSData?
var responseError: NSError?
// When
......
......@@ -110,7 +110,7 @@ class RedirectResponseTestCase: BaseTestCase {
var request: NSURLRequest?
var response: NSHTTPURLResponse?
var data: AnyObject?
var data: NSData?
var error: NSError?
// When
......@@ -145,7 +145,7 @@ class RedirectResponseTestCase: BaseTestCase {
var request: NSURLRequest?
var response: NSHTTPURLResponse?
var data: AnyObject?
var data: NSData?
var error: NSError?
// When
......@@ -185,7 +185,7 @@ class RedirectResponseTestCase: BaseTestCase {
var request: NSURLRequest?
var response: NSHTTPURLResponse?
var data: AnyObject?
var data: NSData?
var error: NSError?
// When
......@@ -225,7 +225,7 @@ class RedirectResponseTestCase: BaseTestCase {
var request: NSURLRequest?
var response: NSHTTPURLResponse?
var data: AnyObject?
var data: NSData?
var error: NSError?
// When
......@@ -267,7 +267,7 @@ class RedirectResponseTestCase: BaseTestCase {
var request: NSURLRequest?
var response: NSHTTPURLResponse?
var data: AnyObject?
var data: NSData?
var error: NSError?
// When
......
......@@ -137,15 +137,15 @@ class URLProtocolTestCase: BaseTestCase {
var request: NSURLRequest?
var response: NSHTTPURLResponse?
var string: AnyObject?
var data: NSData?
var error: NSError?
// When
Alamofire.request(URLRequest)
.response { responseRequest, responseResponse, responseString, responseError in
.response { responseRequest, responseResponse, responseData, responseError in
request = responseRequest
response = responseResponse
string = responseString
data = responseData
error = responseError
expectation.fulfill()
......@@ -156,7 +156,7 @@ class URLProtocolTestCase: BaseTestCase {
// Then
XCTAssertNotNil(request, "request should not be nil")
XCTAssertNotNil(response, "response should not be nil")
XCTAssertNotNil(string, "string should not be nil")
XCTAssertNotNil(data, "data should not be nil")
XCTAssertNil(error, "error should be nil")
if let headers = response?.allHeaderFields as? [String: String] {
......
......@@ -186,7 +186,7 @@ class UploadDataTestCase: BaseTestCase {
var progressValues: [(completedUnitCount: Int64, totalUnitCount: Int64)] = []
var responseRequest: NSURLRequest?
var responseResponse: NSHTTPURLResponse?
var responseData: AnyObject?
var responseData: NSData?
var responseError: NSError?
// When
......@@ -259,7 +259,7 @@ class UploadMultipartFormDataTestCase: BaseTestCase {
var formData: MultipartFormData?
var request: NSURLRequest?
var response: NSHTTPURLResponse?
var data: AnyObject?
var data: NSData?
var error: NSError?
// When
......@@ -316,7 +316,7 @@ class UploadMultipartFormDataTestCase: BaseTestCase {
var request: NSURLRequest?
var response: NSHTTPURLResponse?
var data: AnyObject?
var data: NSData?
var error: NSError?
// When
......@@ -593,7 +593,7 @@ class UploadMultipartFormDataTestCase: BaseTestCase {
var progressValues: [(completedUnitCount: Int64, totalUnitCount: Int64)] = []
var request: NSURLRequest?
var response: NSHTTPURLResponse?
var data: AnyObject?
var data: NSData?
var error: NSError?
// When
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册