低版本Swift/macOS下基于OpenCombine兼容@Published方案
问题背景
正在开发一款不依赖SwiftUI的macOS应用向后兼容版本,当前目标运行系统及配套Swift版本均不支持Combine框架的@Published属性声明特性。目前已接入OpenCombine框架模拟Combine核心功能,整体运行正常,但框架暂未提供@Published声明支持。
由于无法直接使用Swift原生@Published指令,需要实现等效特性:最初考虑通过@propertyWrapper特性自定义实现相关逻辑,配合#if .. #endif预处理宏做版本隔离,让支持原生Combine与@Published的高版本Swift环境可复用同一份代码。
说明:Combine框架可独立于SwiftUI使用,本次需求目标为脱离SwiftUI使用Combine设计模式,不涉及SwiftUI相关解决方案,可通过#if !canImport(Combine)这类预处理指令限制自定义实现的生效范围,相关问题已同步反馈至OpenCombine项目Issue区。
相关代码示例
ObservableObject定义示例
import OpenCombine class SomeObservableClass : OpenCombine.ObservableObject { @Published var highlighted = false // 当前环境不支持@Published特性 }
NSViewController端订阅示例
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) } } }
初步设计的@propertyWrapper实现草稿
@propertyWrapper struct Published<T> { var wrappedValue: T { willSet { /*...*/ } didSet { /*...*/ } } init(wrappedValue: T) { // * -- 核心实现逻辑待补充 -- */ /* 可针对不同类型做特殊处理 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 } }
问题更新
添加typealias Published = OpenCombine.Published后已解决属性包装器识别问题,但出现新的类型不匹配报错:
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)
尝试添加typealias Scheduler = OpenCombine.Scheduler也未能解决该报错。
内容的提问来源于stack exchange,提问作者Ol Sen
相关产品推荐
相关产品推荐

