.send() 和 .sink() 似乎不再适用于 Xcode 11 Beta 5 中的 PassthroughSubject
Posted
技术标签:
【中文标题】.send() 和 .sink() 似乎不再适用于 Xcode 11 Beta 5 中的 PassthroughSubject【英文标题】:.send() and .sink() do not seem to work anymore for PassthroughSubject in Xcode 11 Beta 5 【发布时间】:2019-12-07 19:09:03 【问题描述】:在下面的代码中,当按下按钮时,应该在控制台中打印“Test”,但事实并非如此。该事件不通过发布者发送。 知道 Xcode 11 Beta 5 中的 PassthroughSubject 发生了什么吗? (在 Xcode 11 Beta 4 中运行良好)
var body: some View
let publisher = PassthroughSubject<String, Never>()
publisher.sink (str) in
print(str)
return Button("OK")
publisher.send("Test")
附:我知道按下按钮时还有其他方法可以打印字符串,我只想展示一个简单的发送接收示例
【问题讨论】:
【参考方案1】:.sink()
返回一个AnyCancellable
对象。你永远不应该忽视它。 永远不要这样做:
// never do this!
publisher.sink ...
// never do this!
let _ = publisher.sink ...
如果将其分配给变量,请确保它不是短命的。一旦可取消对象被释放,订阅也会被取消。
// if cancellable is deallocated, the subscription will get cancelled
let cancellable = publisher.sink ...
既然您要求在视图中使用sink
,我将发布一种方法。但是,在视图中,您可能应该改用.onReceive()
。它更简单。
使用接收器:
在视图中使用它时,您需要使用@State
变量,以确保它在生成视图主体后仍然存在。
DispatchQueue.main.async
是必需的,以避免在视图更新时修改状态。否则会出现运行时错误。
struct ContentView: View
@State var cancellable: AnyCancellable? = nil
var body: some View
let publisher = PassthroughSubject<String, Never>()
DispatchQueue.main.async
self.cancellable = publisher.sink (str) in
print(str)
return Button("OK")
publisher.send("Test")
使用.onReceive()
struct ContentView: View
var body: some View
let publisher = PassthroughSubject<String, Never>()
return Button("OK")
publisher.send("Test")
.onReceive(publisher) str in
print(str)
【讨论】:
为了解除订阅,我使用了这样的东西:self.cancellable = publisher.sink(receiveCompletion: (completion) in self.cancellable = nil , receiveValue: (str) in print(str) )
。这是正确的解决方案还是有更好的解决方案?
我不是Combine方面的专家,但它似乎是正确的;-)
作为一个 Combine 和响应式初学者,对于非常简单的任务,周围的许多示例似乎过于复杂:struct ContentView: View @State var string: String = "" didSet print(string) var body: some View return Button("OK") self.string = "Test"
抱歉内联代码。为什么我们要使用主题?我猜是因为它开辟了使用运算符等的机会?【参考方案2】:
订阅接收器时缺少 .store。 您可以使用 .onReceive,但您的代码没有接收到值,因为您需要添加 .store(in: &subscription)
var body: some View
var subscription = Set<AnyCancellable>()
let publisher = PassthroughSubject<String, Never>()
publisher.sink (str) in
print(str)
.store(in: &subscription)
return Button("OK")
publisher.send("Test")
【讨论】:
以上是关于.send() 和 .sink() 似乎不再适用于 Xcode 11 Beta 5 中的 PassthroughSubject的主要内容,如果未能解决你的问题,请参考以下文章
带有视图的 UIView 过渡和设置框架不再适用于 iOS 8
UITableView scrollToRow 在添加新行后不再适用于 iOS 11
在 Eclipse Corrosion 上调试 rust 不再适用于全新安装