AlamoFire用于JSON请求的异步completionHandler

The*_*0s3 78 swift alamofire

使用AlamoFire框架后,我注意到completionHandler在主线程上运行.我想知道下面的代码是否是在完成处理程序中创建Core Data导入任务的好方法:

Alamofire.request(.GET, "http://myWebSite.com", parameters: parameters)
            .responseJSON(options: .MutableContainers) { (_, _, JSON, error) -> Void in
                dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), { () -> Void in
                    if let err = error{
                        println("Error:\(error)")
                        return;
                    }

                    if let jsonArray = JSON as? [NSArray]{                       
                        let importer = CDImporter(incomingArray: jsonArray entity: "Artist", map: artistEntityMap);

                    }
                });
            }
Run Code Online (Sandbox Code Playgroud)

cno*_*oon 154

这是一个非常好的问题.你的方法是完全有效的.但是,Alamofire实际上可以帮助您更精简这一点.

您的示例代码调度队列细分

在示例代码中,您将在以下调度队列之间跳转:

  1. NSURLSession调度队列
  2. TaskDelegate调度队列用于验证和序列化程序处理
  3. 用于调用完成处理程序的主调度队列
  4. JSON处理的高优先级队列
  5. 用于更新用户界面的主调度队列(如有必要)

如你所见,你到处都是跳来跳去的.让我们来看看利用Alamofire内部强大功能的另一种方法.

Alamofire响应调度队列

Alamofire拥有一种内置于其自身低级处理中的最佳方法.response如果您选择使用自定义调度队列,则最终由所有自定义响应序列化程序调用的单个方法都支持自定义调度队列.

虽然GCD在调度队列之间跳跃是惊人的,但您希望避免跳转到繁忙的队列(例如主线程).通过在异步处理过程中消除跳回主线程,您可以大大加快速度.以下示例演示了如何使用Alamofire逻辑直接开箱即用.

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

        // You are now running on the concurrent `queue` you created earlier.
        println("Parsing JSON on thread: \(NSThread.currentThread()) is main thread: \(NSThread.isMainThread())")

        // Validate your JSON response and convert into model objects if necessary
        println(JSON)

        // To update anything on the main thread, just jump back on like so.
        dispatch_async(dispatch_get_main_queue()) {
            println("Am I back on the main thread: \(NSThread.isMainThread())")
        }
    }
)
Run Code Online (Sandbox Code Playgroud)

Alamofire 3.x(Swift 2.2和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
        // You are now running on the concurrent `queue` you created earlier.
        print("Parsing JSON on thread: \(NSThread.currentThread()) is main thread: \(NSThread.isMainThread())")

        // Validate your JSON response and convert into model objects if necessary
        print(response.result.value)

        // To update anything on the main thread, just jump back on like so.
        dispatch_async(dispatch_get_main_queue()) {
            print("Am I back on the main thread: \(NSThread.isMainThread())")
        }
    }
)
Run Code Online (Sandbox Code Playgroud)

Alamofire 4.x(斯威夫特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
            // You are now running on the concurrent `queue` you created earlier.
            print("Parsing JSON on thread: \(Thread.current) is main thread: \(Thread.isMainThread)")

            // Validate your JSON response and convert into model objects if necessary
            print(response.result.value)

            // To update anything on the main thread, just jump back on like so.
            DispatchQueue.main.async {
                print("Am I back on the main thread: \(Thread.isMainThread)")
            }
        }
    )
Run Code Online (Sandbox Code Playgroud)

Alamofire Dispatch Queue Breakdown

以下是此方法涉及的不同调度队列的细分.

  1. NSURLSession调度队列
  2. TaskDelegate调度队列用于验证和序列化程序处理
  3. 用于JSON处理的自定义管理器并发调度队列
  4. 用于更新用户界面的主调度队列(如有必要)

摘要

通过消除第一跳到主调度队列,您已经消除了潜在的瓶颈,并且您已经使整个请求和处理异步.真棒!

话虽如此,我不能强调要熟悉Alamofire真正起作用的内部是多么重要.你永远不知道什么时候你可以找到真正可以帮助你改进自己代码的东西.

  • 感谢@cnoon的详尽解释.似乎`response`方法的第二个参数现在称为`responseSerializer`而不是`serializer`(在Alamofire 3.0中).这导致了"无法调用非函数类型的值'NSHTTPURLResponse?''错误让我感到困惑. (3认同)