Combine学习笔记
作者:@zwvista
本文为作者原创,转载请注明出处:https://www.cnblogs.com/zwvista/p/16574993.html
目录
Combine
Publisher Operator Subscriber
Subject
Subscriber Cancellable
AnyPublisher AnyCancellable
@Published
Combine
Combine是一个函数响应式编程库。
Publisher Operator Subscriber
Publisher(发布者)生成并发布数据。Publisher 是一个协议。
- 发布者可以发布0个1个或多个数据,然后正常结束或出错。
- 发布者的类型由所发布的数据(output,输出)的类型和所发生的错误(failure,失败)的类型构成。
<Output Type, Failure Type>
Operator(操作符)响应和更改数据。
- 操作符的输入类型由所接收的数据(input,输入)的类型和所接收的错误(failure,失败)的类型构成。
- 操作符的输出类型由所生成的数据(output,输出)的类型和所发生的错误(failure,失败)的类型构成。
<Input Type, Failure Type>
to<Output Type, Failure Type>
Subscriber(订阅者)订阅数据。Subscriber 是一个协议。
- 订阅者的类型由所接收的数据(input,输入)的类型和所接收的错误(failure,失败)的类型构成。
<Input Type, Failure Type>
// Publisher Just(5) // Operator .map { value -> String in return "a string" } // Subscriber .sink { receivedValue in print("The end result was \(receivedValue)") }
Subject
Subject 是指遵循 Subject 协议的特殊发布者。Subject 协议继承自 Publisher 协议。
Subject 通过该协议中的 .send(_:)
方法来发布数据。
常用 Subject 有 CurrentValueSubject 和 PassthroughSubject。
- PassthroughSubject 没有初值,没有当前状态(值),订阅者无法接收订阅之前发布的数据。
PassthroughSubject 是门铃,没有开关状态,只有在家才能接收其信息。 - CurrentValueSubject 有初值,有当前状态(值),订阅者可以接收订阅之前最后发布的数据。
CurrentValueSubject 是电灯,有开关状态,回家即可观察其状态。
PassthroughSubject vs. CurrentValueSubject explained
let relay = PassthroughSubject<String, Never>() let subscription = relay.sink { value in print("subscription1 received value: \(value)") } relay.send("Hello") relay.send("World!") /* subscription1 received value: Hello subscription1 received value: World! */
let variable = CurrentValueSubject<String, Never>("") variable.send("Initial text") let subscription2 = variable.sink { value in print("subscription2 received value: \(value)") } variable.send("More text") /* subscription2 received value: Initial text subscription2 received value: More text */
Subscriber Cancellable
常用订阅者有 sink 和 assign。
sink 使用回调函数来处理结果值。
assign 使用结果值来设置其他值。
assign(to:on:)
将结果值赋予其他某个对象的某个属性。
assign(to:)
将结果值赋予其他某个Publisher。
Cancellable (可取消)是一个协议。
sink 和 assign(to:on:)
返回 Cancellable 的实例。
通过调用 Cancellable 协议的 cancel 方法可以取消订阅。
let cancellable = publishingSource.sink { someValue in print(".sink() received \(someValue)") } // cancellable.cancel() let cancellable = publishingSource .receive(on: RunLoop.main) .assign(to: \.isEnabled, on: yourButton) // cancellable.cancel() publishingSource.assign(to: &publishingSource2)
AnyPublisher AnyCancellable
AnyPublisher 为遵循 Publisher 协议的具体类。
通过调用 Publisher 协议的 eraseToAnyPublisher 方法可以将任何 Publisher 对象转化为 AnyPublisher 对象,方便统一处理并隐藏真实类型。
AnyCancellable 为遵循 Cancellable 协议的具体类。
sink 和 assign(to:on:)
返回 AnyCancellable 的实例。
AnyCancellable 的实例必须保存在该类型的变量或容器中。否则该实例会被回收并导致订阅被取消。
let pub: AnyPublisher<String, Never> = ["Here","we","go!"].publisher .eraseToAnyPublisher() var subscriptions = Set<AnyCancellable>() pub.sink { receivedValue in print("received value: \(receivedValue)") }.store(in: &subscriptions) /* received value: Here received value: we received value: go! */
@Published
@Published 是一种提供 Publisher 的属性包装器(Property Wrapper)。
如果 v 是一个 Value 类型的属性,并且 v 属性使用 @Published 修饰,
那么 $v 就是一个 Published<Value>.Publisher
类型的 Publisher。
class Weather { @Published var temperature: Double init(temperature: Double) { self.temperature = temperature } } // temperature 的类型为 Double // $temperature 的类型为 Published<Double>.Publisher let weather = Weather(temperature: 20) let cancellable = weather.$temperature.sink() { print ("Temperature now: \($0)") } weather.temperature = 25 // Temperature now: 20.0 // Temperature now: 25.0
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix