等待完成处理程序完成 - Swift
Wait for completion handler to finish - Swift
我正在尝试检查 UserNotifications 是否已启用,如果未启用我想发出警报。所以我有一个函数 checkAvailability
检查多项内容,包括 UserNotification 授权状态。
func checkAvailabilty() -> Bool {
//
// other checking
//
var isNotificationsEnabled = false
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound], completionHandler: { (granted, error) in
if granted {
isNotificationsEnabled = true
}
else {
isNotificationsEnabled = false
}
})
}
if isNotificationsEnabled {
return true
}
else {
// Throw alert: Remind user to activate notifications
return false
}
}
但是调用完成处理程序为时已晚。该函数已经 returned false
并且之后执行了 colsure 中的代码。
我试图将整个语句 UNUserNotificationCenter.current().requestAuthorization()
放入同步调度队列,但这没有用。
另一种方法是从闭包内部 return 但我不知道如何实现。
是的。因此,正如您所想的那样,这里发生的是调用完成处理程序之前的函数 returns 。所以你想要做的是将一个异步回调传递给 checkAvailability
函数,这样它就会在触发完成处理程序后回调。
func checkAvailability(callback: @escaping (Bool) -> Void) {
//
// other checking
//
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound], completionHandler: { (granted, error) in
if granted {
callback(true)
} else {
callback(false)
}
})
}
你可以像这样调用这个函数...
checkAvailability(callback: { (isAvailable) -> Void in
if isAvailable {
// notifications are available
} else {
// present alert
}
})
请记住,当您要显示警报时,您可能需要显式地将调用分派到主线程,因为完成处理程序可能会在不同的线程上回调。在这种情况下,这就是您想要调用函数并显示警报的方式...
checkAvailability(callback: { (isAvailable) -> Void in
if isAvailable {
// notifications are available
} else {
DispatchQueue.main.async {
// present alert
}
}
})
不要等待,使用完成处理程序,为了方便使用枚举:
enum AuthResult {
case success(Bool), failure(Error)
}
func checkAvailabilty(completion: @escaping (AuthResult) -> ()) {
//
// other checking
//
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound], completionHandler: { (granted, error) in
if error != nil {
completion(.failure(error!))
} else {
completion(.success(granted))
}
})
}
并称它为:
checkAvailabilty { result in
switch result {
case .success(let granted) :
if granted {
print("access is granted")
} else {
print("access is denied")
}
case .failure(let error): print(error)
}
}
在 Swift 5.5 和 async/await 中确实 等待
func checkAvailabilty() async throws -> Bool {
//
// other checking
//
return try await UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound])
}
并称它为:
Task {
do {
let granted = try await checkAvailabilty()
if granted {
print("access is granted")
} else {
print("access is denied")
}
} catch {
print(error)
}
}
代码块
if isNotificationsEnabled {
return true
}
else {
// Throw alert: Remind user to activate notifications
return false
}
在调用 requestAuthorization(options:completionHandler)
后立即调用。
您应该改为在完成处理程序中显示警报:
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound], completionHandler: { (granted, error) in
if !granted {
// Show alert
}
})
您的函数 checkAvailability
不再同步返回 Bool,因为对 requestAuthorization(options:completionHandler)
的调用是异步的。
另一种选择是 return 完成处理程序中的两个参数:
func checkAvailabilty(completion: @escaping (_ granted: Bool, _ error: Error?) -> ()) {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound]) { granted, error in
completion(granted, error)
}
}
用法
checkAvailabilty { granted, error in
guard error == nil else {
// An Authorization error has occurred. Present an alert to the user with the error description.
DispatchQueue.main.async {
let alert = UIAlertController(title: "Alert", message: error?.localizedDescription ?? "Authorization failed. Unknown error.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default))
self.present(alert, animated: true)
}
return
}
if granted {
print("granted") // authorization was successful
} else {
print("denied") // present alert from the main thread
DispatchQueue.main.async {
let alert = UIAlertController(title: "Attention", message: "The App needs you to turn on notifications !!!", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default))
self.present(alert, animated: true)
}
}
}
我正在尝试检查 UserNotifications 是否已启用,如果未启用我想发出警报。所以我有一个函数 checkAvailability
检查多项内容,包括 UserNotification 授权状态。
func checkAvailabilty() -> Bool {
//
// other checking
//
var isNotificationsEnabled = false
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound], completionHandler: { (granted, error) in
if granted {
isNotificationsEnabled = true
}
else {
isNotificationsEnabled = false
}
})
}
if isNotificationsEnabled {
return true
}
else {
// Throw alert: Remind user to activate notifications
return false
}
}
但是调用完成处理程序为时已晚。该函数已经 returned false
并且之后执行了 colsure 中的代码。
我试图将整个语句 UNUserNotificationCenter.current().requestAuthorization()
放入同步调度队列,但这没有用。
另一种方法是从闭包内部 return 但我不知道如何实现。
是的。因此,正如您所想的那样,这里发生的是调用完成处理程序之前的函数 returns 。所以你想要做的是将一个异步回调传递给 checkAvailability
函数,这样它就会在触发完成处理程序后回调。
func checkAvailability(callback: @escaping (Bool) -> Void) {
//
// other checking
//
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound], completionHandler: { (granted, error) in
if granted {
callback(true)
} else {
callback(false)
}
})
}
你可以像这样调用这个函数...
checkAvailability(callback: { (isAvailable) -> Void in
if isAvailable {
// notifications are available
} else {
// present alert
}
})
请记住,当您要显示警报时,您可能需要显式地将调用分派到主线程,因为完成处理程序可能会在不同的线程上回调。在这种情况下,这就是您想要调用函数并显示警报的方式...
checkAvailability(callback: { (isAvailable) -> Void in
if isAvailable {
// notifications are available
} else {
DispatchQueue.main.async {
// present alert
}
}
})
不要等待,使用完成处理程序,为了方便使用枚举:
enum AuthResult {
case success(Bool), failure(Error)
}
func checkAvailabilty(completion: @escaping (AuthResult) -> ()) {
//
// other checking
//
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound], completionHandler: { (granted, error) in
if error != nil {
completion(.failure(error!))
} else {
completion(.success(granted))
}
})
}
并称它为:
checkAvailabilty { result in
switch result {
case .success(let granted) :
if granted {
print("access is granted")
} else {
print("access is denied")
}
case .failure(let error): print(error)
}
}
在 Swift 5.5 和 async/await 中确实 等待
func checkAvailabilty() async throws -> Bool {
//
// other checking
//
return try await UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound])
}
并称它为:
Task {
do {
let granted = try await checkAvailabilty()
if granted {
print("access is granted")
} else {
print("access is denied")
}
} catch {
print(error)
}
}
代码块
if isNotificationsEnabled {
return true
}
else {
// Throw alert: Remind user to activate notifications
return false
}
在调用 requestAuthorization(options:completionHandler)
后立即调用。
您应该改为在完成处理程序中显示警报:
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound], completionHandler: { (granted, error) in
if !granted {
// Show alert
}
})
您的函数 checkAvailability
不再同步返回 Bool,因为对 requestAuthorization(options:completionHandler)
的调用是异步的。
另一种选择是 return 完成处理程序中的两个参数:
func checkAvailabilty(completion: @escaping (_ granted: Bool, _ error: Error?) -> ()) {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound]) { granted, error in
completion(granted, error)
}
}
用法
checkAvailabilty { granted, error in
guard error == nil else {
// An Authorization error has occurred. Present an alert to the user with the error description.
DispatchQueue.main.async {
let alert = UIAlertController(title: "Alert", message: error?.localizedDescription ?? "Authorization failed. Unknown error.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default))
self.present(alert, animated: true)
}
return
}
if granted {
print("granted") // authorization was successful
} else {
print("denied") // present alert from the main thread
DispatchQueue.main.async {
let alert = UIAlertController(title: "Attention", message: "The App needs you to turn on notifications !!!", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default))
self.present(alert, animated: true)
}
}
}