requestAuthorisation
работает асинхронно, поэтому confirmAuthorization
снова вызывается до того, как диалоговое окно авторизации будет представлено пользователю.
Как правило, в этом типе шаблона (желание вызывать что-либо рекурсивно в асинхронных шаблонах) решение состоит в том, чтобы переместить рекурсивный вызов в обработчик завершения асинхронного метода. Но в этом случае после того, как пользователь получит диалоговое окно авторизации, он либо примет, либо отклонит его, и нет смысла беспокоиться о состоянии «что, если оно еще не определено». Итак, суть в том, что в этом сценарии рекурсия не нужна или не нужна.
При этом вы, очевидно, do хотите вернуть статус вызывающей стороне. Но шаблон выдачи ошибок не сработает, потому что вам нужно обработать асинхронную ситуацию (когда разрешение не было определено, и нам нужно было представить диалоговое окно подтверждения).
Поэтому я предлагаю вместо этого использовать шаблон обработчика завершения:
private func confirmAuthorization(for entityType: EKEntityType, completion: @escaping (EKAuthorizationStatus) -> Void) {
let status = EKEventStore.authorizationStatus(for: entityType)
switch status {
case .notDetermined:
requestAuthorisation(for: entityType, completion: completion)
default:
completion(status)
}
}
private func requestAuthorisation(for entityType: EKEntityType, completion: @escaping (EKAuthorizationStatus) -> Void) {
store.requestAccess(to: entityType) { _, _ in
DispatchQueue.main.async {
completion(EKEventStore.authorizationStatus(for: entityType))
}
}
}
Или вы можете уменьшить это до одного метода:
private func confirmAuthorization(for entityType: EKEntityType, completion: @escaping (EKAuthorizationStatus) -> Void) {
let status = EKEventStore.authorizationStatus(for: entityType)
switch status {
case .notDetermined:
store.requestAccess(to: entityType) { _, _ in
DispatchQueue.main.async {
completion(EKEventStore.authorizationStatus(for: entityType))
}
}
default:
completion(status)
}
}
Тогда вы можете:
confirmAuthorization(for: .event) { status in
switch status {
case .authorized:
// proceed
default:
// handle non-authorized process here
}
}
// But, remember, the above runs asynchronously, so do *not*
// put any code contingent upon the auth status here. You
// must put code contingent upon authorization inside the above
// completion handler closure.
//