swift - Swift 中 `Combine` 和 `didSet` 有什么区别?

标签 swift swiftui combine

我最近致力于 SwiftUI 并开始以声明式方式编写代码。但这里出现了困惑。如下所示,在将 song 分配给任何值后,我想 (1) 加载歌曲数据并 (2) 通过设置 isInfoViewShown 显示 View 。

我假设 didSet{}Combine @Published .sink{} 可以互换执行操作。所以我想问一下他们之间有什么区别?在我看来,didSet{} 可以完成 Combine 所做的大部分工作。那么苹果为什么要宣布 Combine 框架呢?

感谢任何帮助。

class InfoViewModel: ObservableObject {
    
    @Published var song: Song? {
        didSet {                      // Here's the didSet{}: [1] load song data
            if let song = song {
                load(song: song)
            }
        }
    }
    
    private var songSelectedSubscription: AnyCancellable?
    
    @Published var isInfoViewShown: Bool = false

    init() {                          // Here's the Combine @Published .sink{}: [2] show the view
        songSelectedSubscription = $song.sink{ self.isInfoViewShown = ($0 == nil ? false : true) }              
    }
}

最佳答案

当然,观察数据变化的方法有很多,KVO、通知中心、didSet、combine 等,所以从某种意义上来说这些东西确实是相似的。但差异是:

一个属性只能有一个 didSet,这使得任何数量的观察者都很难注册对该属性的兴趣。

但是组合的最大好处是:组合管道允许您轻松创建流,例如,将更改流转换为以下流:观察用户输入字符串的更改,对其进行反跳(速率限制)更改,以便我们不会向服务器发送垃圾邮件),过滤这些更改以获取至少 3 个字符长的任何值,并生成一个您可以观察到的新流。 Map/FlatMap 也是一个非常重要的组合运算符,将 a 流转换为 b 流。还可以使用 mergeLatest 等将两个流合并在一起,这样您就可以获取 a 流和 b 流并创建 (a, b) 流,然后将其映射到经过验证的 c 流。

关于swift - Swift 中 `Combine` 和 `didSet` 有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73459298/

相关文章:

ios - 直接调用 Swift 枚举实例方法会创建实例吗?

ios - 如何从 SwiftUI 中的结构体返回值?

firebase - 合并:使用 Future 包装异步调用,但 Future.sink 似乎没有完成

ios - SwiftUI 表情符号键盘隐藏在 ScrollView 中

swiftui - 如何在 SwiftUI 中制作半透明导航栏?

swift - 使用 Combine 合并先前的值

ios - 如果 dataTaskPublisher 有非零数据,那么错误类型是什么?

iOS 组合 : get a strongly typed error from URLSession's dataTaskPublisher

ios - Bitbucket 无法识别我的 Swift 项目

ios - 如何将数据保存到一个 View Controller 中的 CoreData 中,然后让 tableview 在另一个 View Controller 中显示数据?