Skip to content

Instantly share code, notes, and snippets.

@jegnux
Last active October 12, 2021 22:49
Show Gist options
  • Save jegnux/79554d1b1eb200afb1dfca075b6bd478 to your computer and use it in GitHub Desktop.
Save jegnux/79554d1b1eb200afb1dfca075b6bd478 to your computer and use it in GitHub Desktop.
Alternative to @published that works with subclasses
@propertyWrapper
public struct SuperPublished<Value> {
public init(wrappedValue: Value) {
self.wrappedValue = wrappedValue
}
public var wrappedValue: Value
public static subscript<EnclosingSelf: ObservableObject>(
_enclosingInstance observed: EnclosingSelf,
wrapped wrappedKeyPath: ReferenceWritableKeyPath<EnclosingSelf, Value>,
storage storageKeyPath: ReferenceWritableKeyPath<EnclosingSelf, Self>
) -> Value {
get {
observed[keyPath: storageKeyPath].wrappedValue
}
set {
if let publisher = observed.objectWillChange as? Combine.ObservableObjectPublisher {
publisher.send()
}
observed[keyPath: storageKeyPath].wrappedValue = newValue
}
}
}
import PlaygroundSupport
import SwiftUI
import Combine
class Root: ObservableObject {
@Published var rootPublished: Int = 0
@SuperPublished var rootSuperPublished: Int = 0
}
class Child: Root {
@Published var childPublished: Int = 0
@SuperPublished var childSuperPublished: Int = 0
}
struct MyView: View {
@ObservedObject var child = Child()
var body: some View {
VStack(alignment: .leading) {
button("rootPublished", for: \.rootPublished)
button("rootSuperPublished", for: \.rootSuperPublished)
button("childPublished", for: \.childPublished)
button("childSuperPublished", for: \.childSuperPublished)
}
}
func button(
_ title: String,
for keyPath: ReferenceWritableKeyPath<Child, Int>
) -> some View {
HStack {
Text("\(title): \(child[keyPath: keyPath])")
Button(action: { self.child[keyPath: keyPath] += 1 }) {
Text("+= 1")
}
}
}
}
PlaygroundPage.current.liveView = NSHostingView(rootView: MyView())
@jegnux
Copy link
Author

jegnux commented Oct 15, 2020

Oh actually not... This will return a SuperPublished<Value> when using $, while Published<Value> returns a publisher.
But you still should be able to do it by maintaining a CurrentValueSubject<Value>.

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