Swift - Почему DispatchGroup не работает в этой функции?

Я жду idToken ответ перед возвратом переменной.

Пожалуйста, не говорите мне просто использовать обработчик завершения и вызывать его без DispatchGroup. Я знаю, что могу это сделать, но я пытаюсь понять, почему эта логика не работает.

func createToken() -> String {
    
    var token = "empty"
    var group = DispatchGroup()
    group.enter()
    
    let currentUser = Auth.auth().currentUser
    
    currentUser?.getIDTokenForcingRefresh(true) { idToken, error in
        
        token = idToken ?? "error"
        print("Token Set")
        group.leave()
    }
    
    group.wait(timeout: DispatchTime.now() + 10)

    return token
}

Бег:

print("create ")
print(createToken())
print("done")

Вывод:

create 
empty
done
Token Set

1 ответ

Решение

Если getIDTokenForcingRefreshотправляет закрытие обработчика завершения обратно в основную очередь, вы увидите именно то поведение, которое вы описываете. Когда казнь попадает в waitвызов, он заблокирует основной поток. Но если закрытие обработчика завершения отправляется в основную очередь, он не сможет работать до тех пор, пока wait время вызова истекает, и основной поток снова освобождается.

Вы можете подтвердить этот тезис, что getIDTokenForcingRefresh вызывает свой обработчик завершения в основном потоке различными способами:

  • Попробуйте удалить timeout, и в этом случае этот код полностью заблокировался бы, если бы он использовал основную очередь / поток.

  • Распечатать Thread.isMainThread.

  • Добавьте предварительное условие:

    dispatchPrecondition(condition: .onQueue(.main))
    
  • Установите точку останова в этом закрытии и позвольте отладчику сообщить вам, какой поток был использован.

Но вы совершенно правы: wait паттерна следует избегать вообще.

Другие вопросы по тегам