Быстрое объединение с синхронизацией

#swift #combine

#быстрое #объединить

Вопрос:

Я новичок в объединении…. У меня есть функция, у которой есть подписчик, и эта функция вернет значение от издателя, но функция вернет пустое значение, прежде чем дождаться завершения приема …. есть ли способ, которым я могу дождаться приема и присвоить значение возвращаемой переменной функции, а затем вернутьстрока возвращается вызывающему эту функцию.

  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: amp;tokens)
    return state
  

Комментарии:

1. Нет, вы не можете. Это асинхронная функция, поэтому, если вы никогда не имели дела с асинхронным программированием, я настоятельно рекомендую вам ознакомиться с этим. В двух словах, если вы хотите, чтобы вызывающий объект функции получал значение, вам нужно либо реализовать обратный вызов (который предоставит вызывающий объект) и вызвать его внутри .sink , либо, если вызывающий объект ожидает издателя, верните издателя (цепочку перед .sink )

Ответ №1:

В других языках программирования, таких как C #, существует концепция async/await . Вы объявляете часть своей программы как асинхронную с помощью ключевого async слова и ждете результата с await ключевым словом неблокирующим образом. Однако эта концепция не реализована в Swift (даже если она активно обсуждается).

Итак, есть ли альтернатива в Swift? Да, с использованием DispatchSemaphore. Ваш метод должен выглядеть следующим образом:

 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: amp;tokens)

    sema.wait()
    return state
}
  

Комментарии:

1. Асинхронный / ожидающий теперь реализован в Swift 5.5 🙂

2. было бы неплохо обновить предложение swift до github.com/apple/swift-evolution/blob/main/proposals /…