Esta es una muy buena pregunta. Tu enfoque es perfectamente válido. Sin embargo, Alamofire realmente puede ayudarlo a simplificar esto aún más.
Su código de ejemplo Desglose de la cola de despacho
En su código de ejemplo, está saltando entre las siguientes colas de envío:
- Cola de despacho NSURLSession
- TaskDelegate cola de despacho para validación y procesamiento de serializador
- Cola de despacho principal para llamar a su controlador de finalización
- Cola de alta prioridad para el manejo de JSON
- Cola de envío principal para actualizar la interfaz de usuario (si es necesario)
Como puede ver, está saltando por todos lados. Echemos un vistazo a un enfoque alternativo que aprovecha una característica poderosa dentro de Alamofire.
Colas de despacho de respuesta de Alamofire
Alamofire tiene un enfoque óptimo integrado en su propio procesamiento de bajo nivel. El response
método único que finalmente es llamado por todos los serializadores de respuesta personalizados tiene soporte para una cola de despacho personalizada si elige usarla.
Si bien GCD es increíble para saltar entre colas de despacho, desea evitar saltar a una cola que está ocupada (por ejemplo, el hilo principal). Al eliminar el salto de regreso al hilo principal en medio del procesamiento asincrónico, potencialmente puede acelerar las cosas considerablemente. El siguiente ejemplo demuestra cómo hacer esto usando la lógica de Alamofire directamente desde el primer momento.
Alamofire 1.x
let queue = dispatch_queue_create("com.cnoon.manager-response-queue", DISPATCH_QUEUE_CONCURRENT)
let request = Alamofire.request(.GET, "http://httpbin.org/get", parameters: ["foo": "bar"])
request.response(
queue: queue,
serializer: Request.JSONResponseSerializer(options: .AllowFragments),
completionHandler: { _, _, JSON, _ in
println("Parsing JSON on thread: \(NSThread.currentThread()) is main thread: \(NSThread.isMainThread())")
println(JSON)
dispatch_async(dispatch_get_main_queue()) {
println("Am I back on the main thread: \(NSThread.isMainThread())")
}
}
)
Alamofire 3.x (Swift 2.2 y 2.3)
let queue = dispatch_queue_create("com.cnoon.manager-response-queue", DISPATCH_QUEUE_CONCURRENT)
let request = Alamofire.request(.GET, "http://httpbin.org/get", parameters: ["foo": "bar"])
request.response(
queue: queue,
responseSerializer: Request.JSONResponseSerializer(options: .AllowFragments),
completionHandler: { response in
print("Parsing JSON on thread: \(NSThread.currentThread()) is main thread: \(NSThread.isMainThread())")
print(response.result.value)
dispatch_async(dispatch_get_main_queue()) {
print("Am I back on the main thread: \(NSThread.isMainThread())")
}
}
)
Alamofire 4.x (Swift 3)
let queue = DispatchQueue(label: "com.cnoon.response-queue", qos: .utility, attributes: [.concurrent])
Alamofire.request("http://httpbin.org/get", parameters: ["foo": "bar"])
.response(
queue: queue,
responseSerializer: DataRequest.jsonResponseSerializer(),
completionHandler: { response in
print("Parsing JSON on thread: \(Thread.current) is main thread: \(Thread.isMainThread)")
print(response.result.value)
DispatchQueue.main.async {
print("Am I back on the main thread: \(Thread.isMainThread)")
}
}
)
Desglose de la cola de despacho de Alamofire
Aquí está el desglose de las diferentes colas de despacho involucradas con este enfoque.
- Cola de despacho NSURLSession
- TaskDelegate cola de despacho para validación y procesamiento de serializador
- Cola de despacho concurrente del administrador personalizado para el manejo de JSON
- Cola de envío principal para actualizar la interfaz de usuario (si es necesario)
Resumen
Al eliminar el primer salto de regreso a la cola de despacho principal, ha eliminado un posible cuello de botella y ha hecho que toda su solicitud y procesamiento sean asincrónicos. ¡Increíble!
Dicho esto, no puedo enfatizar lo suficiente lo importante que es familiarizarse con los aspectos internos de cómo funciona realmente Alamofire. Nunca se sabe cuándo puede encontrar algo que realmente pueda ayudarlo a mejorar su propio código.
response
método ahora se llama enresponseSerializer
lugar deserializer
(en Alamofire 3.0). Eso provocó unCannot call value of non-function type 'NSHTTPURLResponse?'
error que me confundió un poco.Pequeña actualización para Swift 3.0, Alamofire (4.0.1), Editar para @cnoon respuesta:
let queue = DispatchQueue(label: "com.cnoon.manager-response-queue", qos: .userInitiated, attributes:.concurrent) Alamofire?.request(SERVER_URL, method: .post, parameters: ["foo": "bar"], encoding: JSONEncoding.default,//by default headers: ["Content-Type":"application/json; charset=UTF-8"]) .validate(statusCode: 200..<300).//by default responseJSON(queue: queue, options: .allowFragments, completionHandler: { (response:DataResponse<Any>) in switch(response.result) { case .success(_): break case .failure(_): print(response.result.error) if response.result.error?._code == NSURLErrorTimedOut{ //TODO: Show Alert view on netwok connection. } break } })
fuente
Simplemente complementando la respuesta perfecta de @cnoon, si me gusta
ResponseObjectSerializable
, puede incrustar este comportamiento concurrente en la extensión de solicitud:extension Request { public func responseObject<T: ResponseObjectSerializable>(completionHandler: Response<T, NSError> -> Void) -> Self { let responseSerializer = ResponseSerializer<T, NSError> { request, response, data, error in guard error == nil else { return .Failure(error!) } let JSONResponseSerializer = Request.JSONResponseSerializer(options: .AllowFragments) let result = JSONResponseSerializer.serializeResponse(request, response, data, error) switch result { case .Success(let value): if let response = response, responseObject = T(response: response, representation: value) { return .Success(responseObject) } else { let failureReason = "JSON could not be serialized into response object: \(value)" let error = Error.errorWithCode(.JSONSerializationFailed, failureReason: failureReason) return .Failure(error) } case .Failure(let error): return .Failure(error) } } let queue = dispatch_queue_create("my.queue", DISPATCH_QUEUE_CONCURRENT) return response(queue: queue, responseSerializer: responseSerializer) { response in dispatch_async(dispatch_get_main_queue()) { completionHandler(response) } } } }
fuente