You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

低版本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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 09:15:39