View.onReceive 当视图从层次结构中删除时不会取消订阅
View.onReceive doesn't cancel subscription when the view removed from hierarchy
似乎View.onReceive
在该视图消失后没有取消订阅。当屏幕上没有子视图时,动作会不断被调用。
如何在视图仅可见时保持该订阅有效?
struct BugDemo: View {
var body: some View {
NavigationView {
NavigationLink("Go to child", destination: Child())
}
}
}
struct Child: View {
@State private var date: Date = Date()
var body: some View {
Text(DateFormatter.localizedString(from: date, dateStyle: .medium, timeStyle: .medium))
.navigationBarTitle("Child")
.onReceive(PublisherHolder.shared.publisher) {
print("Child.onReceive")
self.date = [=11=]
}
.onDisappear {
print("Child.onDisappear")
}
}
}
private class PublisherHolder {
static let shared = PublisherHolder()
lazy var publisher: AnyPublisher<Date, Never> = {
Timer.publish(every: 1, on: .main, in: .default)
.autoconnect()
.print()
.eraseToAnyPublisher()
}()
}
这不是 .onReceive
。这是 NavigationView
行为。不管幸运与否,它都会缓存导航堆栈以供重复使用。
如果您改为使用以下 show/hide 作为 Child
,您会看到一切都已正确取消。
使用 Xcode 11.4
测试
@State private var showChild = false
var body: some View {
VStack {
Button("Toggle View") { self.showChild.toggle() }
if showChild {
Child()
}
}
// NavigationView {
// NavigationLink("Go to child", destination: Child())
// }
}
似乎View.onReceive
在该视图消失后没有取消订阅。当屏幕上没有子视图时,动作会不断被调用。
如何在视图仅可见时保持该订阅有效?
struct BugDemo: View {
var body: some View {
NavigationView {
NavigationLink("Go to child", destination: Child())
}
}
}
struct Child: View {
@State private var date: Date = Date()
var body: some View {
Text(DateFormatter.localizedString(from: date, dateStyle: .medium, timeStyle: .medium))
.navigationBarTitle("Child")
.onReceive(PublisherHolder.shared.publisher) {
print("Child.onReceive")
self.date = [=11=]
}
.onDisappear {
print("Child.onDisappear")
}
}
}
private class PublisherHolder {
static let shared = PublisherHolder()
lazy var publisher: AnyPublisher<Date, Never> = {
Timer.publish(every: 1, on: .main, in: .default)
.autoconnect()
.print()
.eraseToAnyPublisher()
}()
}
这不是 .onReceive
。这是 NavigationView
行为。不管幸运与否,它都会缓存导航堆栈以供重复使用。
如果您改为使用以下 show/hide 作为 Child
,您会看到一切都已正确取消。
使用 Xcode 11.4
测试 @State private var showChild = false
var body: some View {
VStack {
Button("Toggle View") { self.showChild.toggle() }
if showChild {
Child()
}
}
// NavigationView {
// NavigationLink("Go to child", destination: Child())
// }
}