I am trying to write a little tool about Notification to convenience myself like:
private let NotificatableUserInfoKey = "Notificatable.userInfoKey"
struct Notificatable<InfoType> {
let name: String
fileprivate var notificationName: Notification.Name {
Notification.Name(name)
}
}
extension Notificatable {
func post(object: Any? = nil, userInfo: InfoType) {
NotificationCenter.default.post(name: notificationName, object: object, userInfo: [NotificatableUserInfoKey: userInfo])
}
struct InfoTypeAny {
struct Notification {
let name: Foundation.Notification.Name
let object: Any?
let userInfo: InfoType
}
}
func subscribe(object: AnyObject? = nil, _ action: @escaping (_ notification: InfoTypeAny.Notification) -> Void) -> Disposable {
return NotificationCenter.default.rx.notification(notificationName, object: object).subscribe(onNext: { noti in
guard let info = noti.userInfo?[NotificatableUserInfoKey] as? InfoType else { return }
action(.init(name: noti.name, object: noti.object, userInfo: info))
})
}
}
and then I want to make A extension to remove userInfo if I don't have it:
extension Notificatable where InfoType == Void {
init(name: String) {
self.name = name
}
func post(object: Any? = nil) {
NotificationCenter.default.post(name: notificationName, object: object, userInfo: nil)
}
struct InfoTypeVoid {
struct Notification {
let name: Foundation.Notification.Name
let object: Any?
}
}
func subscribe(object: AnyObject? = nil, _ action: @escaping (_ notification: InfoTypeVoid.Notification) -> Void) -> Disposable {
return NotificationCenter.default.rx.notification(notificationName, object: object).subscribe(onNext: { noti in
action(.init(name: noti.name, object: noti.object))
})
}
}
but unfortunately it does't work, becase once you create a Notificatable, you can use 2 different subscribe function in the same time , and Swift compiler will throw you an error:
Notificatable(name: "abc").subscribe { (notification) in // Ambiguous use of 'subscribe(object:_:)'
}
So I think is there any possible to make extension when InfoType != Void, or just add an extension else feature by making code like:
private let NotificatableUserInfoKey = "Notificatable.userInfoKey"
struct Notificatable<InfoType> {
let name: String
fileprivate var notificationName: Notification.Name {
Notification.Name(name)
}
}
extension Notificatable where InfoType == Void {
init(name: String) {
self.name = name
}
func post(object: Any? = nil) {
NotificationCenter.default.post(name: notificationName, object: object, userInfo: nil)
}
struct InfoTypeVoid {
struct Notification {
let name: Foundation.Notification.Name
let object: Any?
}
}
func subscribe(object: AnyObject? = nil, _ action: @escaping (_ notification: InfoTypeVoid.Notification) -> Void) -> Disposable {
return NotificationCenter.default.rx.notification(notificationName, object: object).subscribe(onNext: { noti in
action(.init(name: noti.name, object: noti.object))
})
}
} else {
func post(object: Any? = nil, userInfo: InfoType) {
NotificationCenter.default.post(name: notificationName, object: object, userInfo: [NotificatableUserInfoKey: userInfo])
}
struct InfoTypeAny {
struct Notification {
let name: Foundation.Notification.Name
let object: Any?
let userInfo: InfoType
}
}
func subscribe(object: AnyObject? = nil, _ action: @escaping (_ notification: InfoTypeAny.Notification) -> Void) -> Disposable {
return NotificationCenter.default.rx.notification(notificationName, object: object).subscribe(onNext: { noti in
guard let info = noti.userInfo?[NotificatableUserInfoKey] as? InfoType else { return }
action(.init(name: noti.name, object: noti.object, userInfo: info))
})
}
}