Skip to content

Instantly share code, notes, and snippets.

@RuiAAPeres
Last active December 12, 2023 09:51
Show Gist options
  • Save RuiAAPeres/27c592a08baf3b0b95e284de6dc3d54b to your computer and use it in GitHub Desktop.
Save RuiAAPeres/27c592a08baf3b0b95e284de6dc3d54b to your computer and use it in GitHub Desktop.
import Foundation
@propertyWrapper struct Notifier<Value> {
private let identifier: String
var wrappedValue: Value? {
didSet {
NotificationCenter.default.post(name: Notification.Name(identifier), object: wrappedValue)
}
}
init(identifier: String) {
self.identifier = identifier
}
}
@propertyWrapper class Notified<Value> {
private let identifier: String
var wrappedValue: Value?
init(identifier: String) {
self.identifier = identifier
NotificationCenter.default.addObserver(forName: Notification.Name(identifier), object: nil, queue: nil, using: {[weak self] notification in
self?.wrappedValue = notification.object as? Value
})
}
}
struct Person {
@Notifier(identifier: "person.name.changed")
var name: String?
}
class Observer {
@Notified(identifier: "person.name.changed")
var name: String?
}
var person = Person()
var observer = Observer()
observer.name /// nil
person.name = "Hello world"
observer.name /// "Hello world"
@renaudjenny
Copy link

This is really nice and a very good idea.

I would just add a restrictive enum to all of this for identifier key instead of IMO too permissive String:

enum NotificationCenterKey: String {
    case name = "person.name.changed"
}

@propertyWrapper struct Notifier<Value> {
    private let identifier: NotificationCenterKey

    var wrappedValue: Value? {
        didSet {
            NotificationCenter.default.post(name: Notification.Name(identifier.rawValue), object: wrappedValue)
        }
    }
    
    init(identifier: NotificationCenterKey) {
        self.identifier = identifier
    }
}

@propertyWrapper class Notified<Value> {
    private let identifier: NotificationCenterKey

    init(identifier: NotificationCenterKey) {
        self.identifier = identifier

        NotificationCenter.default.addObserver(forName: Notification.Name(identifier.rawValue), object: nil, queue: nil, using: {[weak self] notification in
              self?.wrappedValue = notification.object as? Value
        })
    }
}

struct Person {
  @Notifier(identifier: .name)
  var name: String?

}

class Observer {
  @Notified(identifier: .name)
  var name: String?
}

var person = Person()
var observer = Observer()

observer.name /// nil
person.name = "Hello world"
observer.name /// "Hello world"

@RuiAAPeres
Copy link
Author

Thank you renaudjenny!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment