I have this code, which works and runs with Xcode 15.4 and does not produce a warning.
It is in general what is told to be valid, in this post.
private func waitForUnlockWithTimeout() async throws -> Bool {
let awaitUnlockNotificationTask = Task {
let notification = await NotificationCenter.default.notifications(named: UIApplication.protectedDataDidBecomeAvailableNotification)
print("keychain is available now")
return true
}
let timeoutTask = Task {
try await Task.sleep(nanoseconds: 1_000_000_000)
print("keychain unlock timeout - waited for one second and still locked.")
awaitUnlockNotificationTask.cancel()
}
return await withTaskCancellationHandler {
let result = await awaitUnlockNotificationTask.value
timeoutTask.cancel()
return result
} onCancel: {
awaitUnlockNotificationTask.cancel()
timeoutTask.cancel()
}
}
This code produces a warning in Xcode 16 beta:
No 'async' operations occur within 'await' expression
After reading the docs, I came to the conclusion, that this is kind of an event stream and I can listen to it with for await
.
I changed the code of the first task into this:
let awaitUnlockNotificationTask = Task {
for await notification in NotificationCenter.default.notifications(named: UIApplication.protectedDataDidBecomeAvailableNotification) {
print("keychain is available now")
return true
}
return false
}
This works on Xcode 16 beta, and the warning is gone as well. However, it does not compile with Xcode 15.4 anymore. It says
Expression is ‘async’ but is not marked with ‘await’
Apple docs are also quite interesting. It is not async in the function header, but the docs state:
notifications(named:object:)
Returns an asynchronous sequence of
notifications produced by this center for a given notification name
and optional source object.
What am I missing?