Skip to content

Instantly share code, notes, and snippets.

@PadraigK
Last active February 24, 2024 18:40
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save PadraigK/c6d1bae4337d12508dea8d37cacdf3cc to your computer and use it in GitHub Desktop.
Save PadraigK/c6d1bae4337d12508dea8d37cacdf3cc to your computer and use it in GitHub Desktop.
Wrapping Notifications for Sendability
// Example of wrapping `UIApplication.keyboardDidShowNotification` payload
struct KeyboardDidShowPayload {
let keyboardFrameBegin: CGRect?
let keyboardFrameEnd: CGRect?
}
extension NotificationWrapper where Payload == KeyboardDidShowPayload {
@MainActor static let keyboardDidShow: Self = .init(
name: UIApplication.keyboardDidShowNotification,
parser: NotificationParsing<KeyboardDidShowPayload>() { notification in
guard let userInfo = notification.userInfo,
let begin = userInfo[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue,
let end = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else {
return .init(keyboardFrameBegin: nil, keyboardFrameEnd: nil)
}
return .init(
keyboardFrameBegin: begin.cgRectValue,
keyboardFrameEnd: end.cgRectValue
)
}
)
}
// example call site
class MyWindow: UIWindow {
func observe() async {
for await payload in NotificationCenter.default.notifications(.keyboardDidShow) {
print(payload.keyboardFrameBegin)
}
}
}
struct NotificationWrapper<Payload> {
let name: Notification.Name
let parser: NotificationParsing<Payload>
}
struct NotificationParsing<Payload>: @unchecked Sendable {
let parse: (Notification) -> Payload
}
extension NotificationCenter {
func notifications<Payload>(
_ wrapper: NotificationWrapper<Payload>
) -> AsyncMapSequence<NotificationCenter.Notifications, Payload> {
notifications(named: wrapper.name).map { wrapper.parser.parse($0) }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment