-
Notifications
You must be signed in to change notification settings - Fork 32
Description
Description
Something I noticed today when using NotificationCenter.notifications is that I cant actually use eraseToStream to type erase because Notification does not conform to sendable.
Apple recommends using a .map or .compactMap to take out the value that you need to send, however I noticed that even if you have stripped out the non-sendable type via a map or compact map, eraseToStream still produces errors in swift 6 and warnings in swift 5
Here is an example of observing background refresh status changes:
let notifications = notificationCenter
.notifications(named: UIApplication.backgroundRefreshStatusDidChangeNotification)
.compactMap { notification -> UIBackgroundRefreshStatus? in
guard let application = notification.object as? UIApplication else {
return nil
}
return await application.backgroundRefreshStatus
}
.eraseToStream()The only workaround I have found is to do something like this (rather than using eraseToStream)
let (notificationUpdates, continuation) = AsyncStream<UIBackgroundRefreshStatus>.makeStream()
let task = Task { [notificationCenter, application] in
let notifications = notificationCenter
.notifications(named: UIApplication.backgroundRefreshStatusDidChangeNotification)
.compactMap { notification -> UIBackgroundRefreshStatus? in
guard let application = notification.object as? UIApplication else {
return nil
}
return await application.backgroundRefreshStatus
}
continuation.yield(application.backgroundRefreshStatus)
for await backgroundRefreshStatus in notifications {
continuation.yield(backgroundRefreshStatus)
}
}
// this might not be necessary
continuation.onTermination = { _ in
task.cancel()
}Checklist
- If possible, I've reproduced the issue using the
mainbranch of this package. - This issue hasn't been addressed in an existing GitHub issue or discussion.
Expected behavior
Since AsyncStream and AsyncThrowingStream are capable of handling non-sendable elements, I believe eraseToStream and eraseToThrowingStream should mirror this behavior.
Actual behavior
I get a compiler warning (in swift 5) and an error (in swift 6) when using eraseTo(Throwing)Stream on a sequence with non-sendable elements.
Steps to reproduce
You can reproduce it with this code snippet:
let notifications = notificationCenter
.notifications(named: UIApplication.backgroundRefreshStatusDidChangeNotification)
.compactMap { notification -> UIBackgroundRefreshStatus? in
guard let application = notification.object as? UIApplication else {
return nil
}
return await application.backgroundRefreshStatus
}
.eraseToStream()swift-concurrency-extras version information
1.2.0
Destination operating system
iOS 18.0
Xcode version information
16.0.0
Swift Compiler version information
swift-driver version: 1.115 Apple Swift version 6.0 (swiftlang-6.0.0.9.10 clang-1600.0.26.2)
Target: arm64-apple-macosx15.0
