Need to make two HTTP network requests simultaneou

2019-01-18 00:10发布

问题:

I have a situation where I need to make two HTTP GET requests and handle their results only after both are finished. I have a completion handler on each individual network request but it isn't helpful as I don't know when data from both requests are retrieved.

I have limited experience with GCD but now that Swift 3 is out, I am trying to figure out how to run multiple tasks and have a single completion handler for them. My research has shown that GCD or NSOperationQueue may be the solution I'm looking for. Can anyone help suggest which tool fits the job and what the code might look like in Swift 3?

回答1:

You should use dispatch groups, entering the group before you issue the request, and leaving the group in the completion handler for the request. So, let's assume, for a second, that you had some method that performed an asynchronous request, but supplied a completion handler parameter that was a closure that will be called when the network request is done:

func perform(request: URLRequest, completionHandler: @escaping () -> Void) { ... }

To start these two concurrent requests, and be notified when they're done, you'd do something like:

let group = DispatchGroup()

group.enter()
perform(request: first) {
    group.leave()
}

group.enter()
perform(request: second) {
    group.leave()
}

group.notify(queue: .main) {
    print("both done")
}

Clearly, your implementation of perform(request:) may vary significantly (e.g. you might have the closure pass the data back), but the pattern is the same whether you are writing your own networking code with URLSession or using Alamofire. Just use GCD groups, entering the group when you create the requests, and leaving the group in the completion handler of the asynchronous request.



回答2:

Source: How do I write dispatch_after GCD in Swift 3? You can use dispatch_group for that. For example (ObjC code):

dispatch_group_t group = dispatch_group_create();

//startOperation1
dispatch_group_enter(group);

//finishOpeartion1
dispatch_group_leave(group);


//startOperation2
dispatch_group_enter(group);

//finishOpeartion2
dispatch_group_leave(group);


//Handle both operations completion
dispatch_group_notify(group, dispatch_get_main_queue(), ^{ 
//code here
});