Semaphore

class  a {
    b().download ({ data in
    })
}
class  b{
    func download (downloadedData: @escaping (_ data: Data? ) -> Void )  {
        c().download()

    }
}
class c {

    func download () -> Data {

        let semaphore = DispatchSemaphore(value: 0)

          NetworkManager().downloadRequest: { (result: Result<Data, Error>) in
                                            switch result {
                                            case .success(let success)
                                                ......

                                             case .failure(let error):
                                              .....
                                            }

                                            semaphore.signal()
                                   }
                        )
        semaphore.wait()
        return data
    }
}

Class a initiates the download and class c interacts with network manager to download the data. Class c issues semaphore wait as soon as it sends request to download the data and issues signal when download completes. Is there a way to issue signal from class a when download is in progress. Basically class a should be able to skip wait by issuing signal command

Answered by OOPer in 682759022

Ok, what is the best practice other than async/wait as I have to implement before this fall.

Already written:

Use completion handler properly

Something like this:

class A {
    func aMethod() {
        B().download(downloadedData: { data in
            guard let data = data else {
                return
            }
            //Use `data` here...
        })
    }
}
class B {
    func download(downloadedData: @escaping (_ data: Data? ) -> Void )  {
        NetworkManager().downloadRequest {result in
            switch result {
            case .success(let data):
                //.....
                downloadedData(data)
            case .failure(let error):
                print(error)
                //...
                downloadedData(nil)
            }
        }
    }
}

There's one simple principle: Never try to use asynchronous methods synchronously. You may want to use semaphores when you have multiple background threads and make them work together with some limited resources. But never for just waiting an asynchronous task to finish.

Class c issues semaphore wait

That's a super-bad practice in programming iOS or macOS (or any other GUI platforms that main thread may have special meaning). You need to find another way than using semaphore.

Are you saying using semaphores to wait until download is complete a bad practice? If so, can you suggest a good practice?

Are you saying using semaphores to wait until download is complete a bad practice?

Sure.

 If so, can you suggest a good practice?

Use completion handler properly, or async/await if you can target new OSs coming this fall.

Ok, what is the best practice other than async/wait as I have to implement before this fall.

You should watch WWDC sessions an async/wait. They explain in detail how to use, how it compares with completion handlers and semaphores. There are 5 or 6 of them, really instructive.

Accepted Answer

Ok, what is the best practice other than async/wait as I have to implement before this fall.

Already written:

Use completion handler properly

Something like this:

class A {
    func aMethod() {
        B().download(downloadedData: { data in
            guard let data = data else {
                return
            }
            //Use `data` here...
        })
    }
}
class B {
    func download(downloadedData: @escaping (_ data: Data? ) -> Void )  {
        NetworkManager().downloadRequest {result in
            switch result {
            case .success(let data):
                //.....
                downloadedData(data)
            case .failure(let error):
                print(error)
                //...
                downloadedData(nil)
            }
        }
    }
}

There's one simple principle: Never try to use asynchronous methods synchronously. You may want to use semaphores when you have multiple background threads and make them work together with some limited resources. But never for just waiting an asynchronous task to finish.

Semaphore
 
 
Q