Reputation: 3348
working on backward compatibility for an macOS App that does not make use of SwiftUI but makes use of Combine
Framework feature @Published
declarations that is also not available in this particular targeted System and also not in this Swift version. The feature set that Combine offers is mimicked with OpenCombine
see Github framework and seems to work. But @Published declarations are not available (yet).
As this Swift @Published
directive can't be expressed in code how could i (hopefully) declare such feature instead?
My thought is i could make use of the @propertyWrapper
feature instead and implement some extra function to make it work..
for discussion..
in the OpenCombine.ObservableObject
aka ObservableObject
is some property
import OpenCombine
class SomeObservableClass : OpenCombine.ObservableObject {
@Published var highlighted = false //where @Published feature is not available
}
and on the other side in a NSView subclass
import OpenCombine
class SomeViewController: NSViewController {
private var cancellables = Set<AnyCancellable>()
override var representedObject: Any? {
didSet {
guard let observedObject = representedObject as? SomeObservableClass,
isViewLoaded else { return }
observedObject.$highlighted
.receive(on: DispatchQueue.main)
.sink { [weak self] newValue in
self?.overlayView.needsDisplay = true
}
.store(in: &cancellables)
}
}
}
and the following looks promising to me, at least it would allow to mimic "@Published" directive manually in some way. The propertyWrapper i would place in #if .. #endif
marks to be able to have the same codebase for Swift that supports Combine & @Published features then
@propertyWrapper
struct Published<T> {
var wrappedValue: T {
willSet { /*...*/ }
didSet { /*...*/ }
}
init(wrappedValue: T) {
// * -- maybe magic here! -- */
/* or do more specific stuff.. ^^
switch (wrappedValue) {
//case is Optional<Any>.Type :
//break
case is Bool :
break
case is Error :
break
case is Optional<Error>.Type :
break
default: break
}
*/
self.wrappedValue = wrappedValue
}
}
Reminder: Combine is an Apple Framework that is heavily used in the SwiftUI Framework but of course also available without. So targeting SwiftUI solutions are not really desired as thats the whole point to be able to use the "Combine-Design-pattern" without SwiftUI. link to Github issue i opened
Reminder2: we also have preprocessor directives like #if !canImport(Combine)
or similar to limit where it would be allowed to be applied
EDIT1: very likely my issue can also be some troubleing typealias
rule. Because
typealias Published = OpenCombine.Published
fixed the propertywrapper issue, instead i am facing the following
observedObject.$highlighted
.receive(on: DispatchQueue.main) //<---- Argument type 'DispatchQueue' does not conform to expected type 'Scheduler'
.sink { [weak self] newValue in
self?.overlayView.needsDisplay = true
}
.store(in: &cancellables)
likewise typealias Scheduler = OpenCombine.Scheduler
did not fix that as i assumed.
Upvotes: 2
Views: 307
Reputation: 3348
for the moment it seems indeed some @propertyWrapper is the solution to allow some
@Published
var somethingToObserve : Type
declaration in Xcode 11.3.1 targeting macOS10.14 with Swift 5.. in front to do the magic.
But also some little change of DispatchQue.main
to DispatchQue.main.ocombine
import OpenCombine
import OpenCombineDispatch
and declaration of the observable
class SomeObservable: OpenCombine.ObservableObject
{
//...
@Published var someobservable: MyType
//...
}
and on the "receiver" side..
typealias Published = OpenCombine.Published
// and somewhere below...
someObserveable.$highlighted
.receive(on: DispatchQueue.main.ocombine)
.sink { [weak self] newValue in
self?.overlayView.needsDisplay = true
}
.store(in: &cancellables)
compiles flawless.
Upvotes: 0