Swift Combine with Sync

2.9k views Asked by At

I am new to combine.... I have a function that has a subscriber, and that function will return a value from the publisher, but the function will return an empty value before waiting for sink to complete.... is there a way I can wait for the sink and assign the value to the function return variable, then return the String back to the caller of this function.

 func getState() -> String{
    
    var state = ""
    let statesub = API.getCheckedState(employeeId: "342344", user: user!)
    statesub
        .mapError({ (error) -> APIError in // 5
            NSLog(error.errorDescription!)
            return error
        })
        .sink(receiveCompletion: { _ in},
              receiveValue:{
                NSLog("State : \($0.state)")
                state = $0.state
              })
        .store(in: &tokens)
    return state
1

There are 1 answers

2
Nikolai On

In other programming languages, such as C#, there is the concept of async/await. You declare a part of your program as asynchronous by the keyword async and wait for the result with the await keyword in a non-blocking manner. However, this concept is not implemented in Swift (even tough it is heavily discussed).

So, is there an alternative in Swift? Yes, using a DispatchSemaphore. Your method should look like:

func getState() -> String {
    var state = ""
    var sema = DispatchSemaphore(value: 0)

    let statesub = API.getCheckedState(employeeId: "342344", user: user!)
    statesub
        .mapError({ (error) -> APIError in // 5
            NSLog(error.errorDescription!)
            return error
        })
        .sink(receiveCompletion: { _ in},
              receiveValue: {
                defer { sema.signal() }

                NSLog("State : \($0.state)")
                state = $0.state
              })
        .store(in: &tokens)

    sema.wait()
    return state
}