Remember from previous projects there was a requirement that some of the interface calls should be placed in the non-main thread, and there was a sequential requirement. NSURLConnection was not deprecated at that time, and was implemented using sendSynchronousRequest and GCD, which looks something like this.

Dispatch_queue_t queue = dispatch_queue_create("xxxxx", DISPATCH_QUEUE_SERIAL); // interface 1 joins dispatch_async(queue, ^{ NSData *data = [NSURLConnection sendSynchronousRequest:xxx returningResponse:xx error:xx]; }]; // interface 2 joins dispatch_async(queue, ^{ NSData *data = [NSURLConnection sendSynchronousRequest:xxx returningResponse:xx error:xx]; }]; .Copy the code

However, after NSURLConnection is changed into URLSession, the data returned in URLSession are all asynchronous blocks and proxies, and there is no synchronous request. So the idea is to sleep first, wait until the callback in the sleep stop, return data. You can actually do this using NSCondition. The implementation is as follows.

func testUrl(a) -> Data? {
    var reData: Data?
    let cond = NSCondition()
    cond.lock()
    URLSession.shared.dataTask(with: URL.init(string: "https://www.baidu.com")! { (data, resp, error)in
        reData = data
        cond.signal()
    }.resume()
    cond.wait()
    cond.unlock()
    return reData
}
// The default is serial queue
let queue = DispatchQueue.init(label: "jj", attributes: [])
queu.async {
    let data1 = testUrl()
}
queu.async {
    let data2 = testUrl()
}
// The interface can be called sequentially to process the data.
Copy the code

Similar requirements can be achieved with DispatchGroup.

func testUrl11(a) -> Data? {
    var reData: Data?
    let group = DispatchGroup()
    group.enter()
    URLSession.shared.dataTask(with: URL.init(string: "https://www.baidu.com")! { (data, resp, error)in
        reData = data
        group.leave()
    }.resume()
    group.wait()
    return reData
}
queu.async {
    let data3 = testUrl11()
}
queu.async {
    let data4 = testUrl11()
}
Copy the code

Pay attention to

  1. I did not use these two methods in the project, so I am not sure whether there are bugs.
  2. useNSConditionThere are many problems.
    • Due to thebroadcastCan wake up all the dead-waitMethod blocks the thread. So call it somewhere elsebroadcastThe method will affect this.
    • According to apple’s official documentation,-signalThe method itself is not completely guaranteed to be accurate, and there may be other threads that are not calling-signalMethod, but bywaitThe thread is still being woken up.
    • Even if iswaitThe wake up time of the thread is no problem, but is beingwaitAnother risk is that the state of the program may change during the execution of subsequent code.
  3. Because we’re using multithreading here. So use it if you have toNSLockLock to unlock.

reference

  • NSCondition analysis, cage, 1992,2019.01.18 16:31:26