Das ist eine wirklich gute Frage. Ihr Ansatz ist absolut gültig. Alamofire kann Ihnen jedoch dabei helfen, dies noch weiter zu optimieren.
Aufschlüsselung der Beispielcode-Versandwarteschlange
In Ihrem Beispielcode springen Sie zwischen den folgenden Versandwarteschlangen:
- NSURLSession-Versandwarteschlange
- TaskDelegate-Versandwarteschlange zur Validierung und Serialisierungsverarbeitung
- Hauptversandwarteschlange zum Aufrufen Ihres Completion-Handlers
- Warteschlange mit hoher Priorität für die JSON-Behandlung
- Hauptversandwarteschlange zum Aktualisieren der Benutzeroberfläche (falls erforderlich)
Wie Sie sehen können, hüpfen Sie überall herum. Werfen wir einen Blick auf einen alternativen Ansatz, der eine leistungsstarke Funktion in Alamofire nutzt.
Alamofire Response Dispatch Queues
Alamofire verfügt über einen optimalen Ansatz, der in die eigene Verarbeitung auf niedriger Ebene integriert ist. Die einzelne response
Methode, die letztendlich von allen benutzerdefinierten Antwortserialisierern aufgerufen wird, unterstützt eine benutzerdefinierte Versandwarteschlange, wenn Sie diese verwenden möchten.
Während GCD beim Wechseln zwischen Versandwarteschlangen erstaunlich ist, möchten Sie vermeiden, zu einer Warteschlange zu springen, die ausgelastet ist (z. B. zum Hauptthread). Indem Sie den Rücksprung zum Hauptthread während der asynchronen Verarbeitung eliminieren, können Sie die Dinge möglicherweise erheblich beschleunigen. Das folgende Beispiel zeigt, wie dies mithilfe der sofort einsatzbereiten Alamofire-Logik durchgeführt wird.
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 und 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)")
}
}
)
Aufschlüsselung der Alamofire-Versandwarteschlange
Hier ist die Aufschlüsselung der verschiedenen Versandwarteschlangen, die an diesem Ansatz beteiligt sind.
- NSURLSession-Versandwarteschlange
- TaskDelegate-Versandwarteschlange zur Validierung und Serialisierungsverarbeitung
- Gleichzeitige Versandwarteschlange des benutzerdefinierten Managers für die JSON-Verarbeitung
- Hauptversandwarteschlange zum Aktualisieren der Benutzeroberfläche (falls erforderlich)
Zusammenfassung
Indem Sie den ersten Sprung zurück zur Hauptversandwarteschlange eliminieren, haben Sie einen potenziellen Engpass beseitigt und Ihre gesamte Anforderung und Verarbeitung asynchron gemacht. Genial!
Trotzdem kann ich nicht genug betonen, wie wichtig es ist, sich mit den internen Funktionen von Alamofire vertraut zu machen. Sie wissen nie, wann Sie etwas finden, das Ihnen wirklich helfen kann, Ihren eigenen Code zu verbessern.
response
Methode jetztresponseSerializer
eher aufgerufen wird alsserializer
(in Alamofire 3.0). Das verursachte eineCannot call value of non-function type 'NSHTTPURLResponse?'
Fehler, der mich ein bisschen verwirrt hatte.Kleines Update für Swift 3.0, Alamofire (4.0.1), Bearbeiten für @cnoon Antwort:
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 } })
quelle
Wenn Sie die perfekte Antwort von @cnoon ergänzen und mich verwenden möchten,
ResponseObjectSerializable
können Sie dieses gleichzeitige Verhalten in die Anforderungserweiterung selbst einbetten: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) } } } }
quelle