1

How make multiple web services calls by serial queue in swift 4 (i.e. second call start after first call completion)

 func allConcurretExce(completion: @escaping () -> ()) {
    let queue = DispatchQueue(label: "reverseDomain", attributes: .concurrent)
    let group = DispatchGroup()


    queue.async (group: group) {

        print("first call")

      self.userSignIn()


    }


    queue.async (group: group) {
        //group.wait(timeout : .now() + .seconds(3))
        print("second call")
        self.getMeData(token: self.token)


    }

    group.notify(queue: DispatchQueue.main) {
        completion()
    }
}

This is what I am doing when my first call completes i got token and send that token to another call.But what I am achieving now is getting both call at a time which is causing error in my second call.My aim is to get token from first and sent to second without using handler. I want to achieve this by queue.

Ashley Mills
  • 50,474
  • 16
  • 129
  • 160
  • All the API calls are asynchronous in nature, so even if you use a serialized queue, as soon as u make a web service call, thread makes a async call and moves to make second web service call. That means though u achieve serialization in making web service calls you cant achieve the serialization in web service call completion by using plain Serial Queue/OperationQueue. I have achieved the same thing by using Asynchronous Operations and using operationQueue and setting maximum concurrent operations to 1 there by making it effectively Serialized Queue :) – Sandeep Bhandari Aug 01 '18 at 07:39
  • Other alternatives are using promise kit or using blocks to trigger the next web service call once the first web service call ends. But if you are looking at making a generic framework which forces webservice calls to be executed serially you cant use neither promise or blocks (too tight coupled with logic) using Operations and OperationQueue will allow you to write generic framework. Lemme post the link to OperationQueue modification I was talking about. – Sandeep Bhandari Aug 01 '18 at 07:41
  • https://stackoverflow.com/questions/39201284/executing-the-nsoperation-when-all-other-operations-in-nsoperationqueue-finished. Link shows how to override various KVO properties of operation to make it asynchronous and use OperationQueue to achieve real serialization with asynchronous web service call. Though question talks about complexity which is not relevant to your question but should give u a good head start – Sandeep Bhandari Aug 01 '18 at 07:42
  • I have edited my question. – user9294044 Aug 01 '18 at 08:30
  • If all your concern is only for these two methods u dont need dispatch group or anything, simply call userSignIn() first, and in the last statement of userSignIn (obviously in completion block of your API after processing response ) call self.getMeData to start getMetaData after the completion of userSignIn() – Sandeep Bhandari Aug 01 '18 at 08:34
  • @SandeepBhandari I dont wanna use completion handler. And i have few more APIs after this. – user9294044 Aug 01 '18 at 09:09
  • See my question and answer in link posted above that should give you fair idea of how to go ahead with operation and operation queue – Sandeep Bhandari Aug 01 '18 at 09:10

1 Answers1

0

you can achieve this using DispatchSemaphore in swift. This will block your thread until one task is over, then you can start another task. Check the example below.

class HttpClassForGetData: NSObject {

    var result: Any? = nil
    var sem = DispatchSemaphore(value: 0) // create semaphore

    init() {

        // create post request
        let url = URL("example.com")!

        var request = URLRequest(url: url)
        request.httpMethod = "GET"

        let session = URLSession(configuration: URLSessionConfiguration.default, delegate:nil, delegateQueue:OperationQueue.main)
        var DATA = session.uploadTask(withStreamedRequest: request) // use uploadTask with completion handler API here.and in your API call completion block call self.sem.signal() method.
        result = DATA

        // continue work in anybodyclass.swift class
        _ = sem.wait(timeout: .distantFuture) // lock calling thread, put this code at the end
    }

}

And in your API call completion block call self.sem.signal() method. Any doubt please comment.

vivekDas
  • 1,248
  • 8
  • 12