Xcode 11 Beta 5中PassthroughSubject的.send()与.sink()失效问题咨询
Xcode 11 Beta 5中PassthroughSubject事件传递失效的原因及修复
我来给你拆解清楚这个问题——你碰到的是Xcode 11 Beta 5对Combine框架的行为调整,和Beta 4的隐式处理逻辑不一样了。
先看你给出的代码:
var body: some View { let publisher = PassthroughSubject<String, Never>() publisher.sink { (str) in print(str) } return Button("OK") { publisher.send("Test") } }
在Xcode 11 Beta 4里,系统可能隐式帮你保留了sink方法返回的订阅对象,但Beta 5修复了这个非标准的行为,严格遵循了Combine的核心设计规则:订阅产生的Cancellable对象必须被主动持有,否则订阅会立即失效。
你的代码里,调用publisher.sink后没有保存返回的AnyCancellable实例,当body方法执行完毕,这个订阅对象就会被ARC自动回收。等你点击按钮发送"Test"事件时,已经没有订阅者在监听这个PassthroughSubject了,自然控制台不会有任何输出。
修复方案(两种可选)
单个订阅场景:用
@State存储订阅对象
直接把订阅实例存在视图的@State属性中,让视图持有它以维持订阅关系:@State private var cancellable: AnyCancellable? var body: some View { let publisher = PassthroughSubject<String, Never>() cancellable = publisher.sink { (str) in print(str) } return Button("OK") { publisher.send("Test") } }多订阅场景:用
Set<AnyCancellable>统一管理
如果后续需要添加多个订阅,用集合来管理会更灵活:@State private var cancellables = Set<AnyCancellable>() var body: some View { let publisher = PassthroughSubject<String, Never>() publisher.sink { (str) in print(str) }.store(in: &cancellables) return Button("OK") { publisher.send("Test") } }
额外优化建议
你当前把publisher放在body方法内,每次视图刷新都会创建新的PassthroughSubject实例,实际项目中建议把它提升为视图的私有属性,避免重复创建:
private let publisher = PassthroughSubject<String, Never>() @State private var cancellables = Set<AnyCancellable>() var body: some View { publisher.sink { (str) in print(str) }.store(in: &cancellables) return Button("OK") { publisher.send("Test") } }
内容的提问来源于stack exchange,提问作者Sorin Lica
相关产品推荐
相关产品推荐

