Swiftui View.onReceive不';当视图从层次结构中删除时,不能取消订阅

Swiftui View.onReceive不';当视图从层次结构中删除时,不能取消订阅,swiftui,combine,Swiftui,Combine,似乎在视图消失后,View.onReceive不会取消订阅。当屏幕上没有子视图时,会不断调用操作。 当视图仅可见时,如何使订阅保持活动状态 struct BugDemo: View { var body: some View { NavigationView { NavigationLink("Go to child", destination: Child()) } } } struct Child: View {

似乎在视图消失后,
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 = $0
            }
            .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()
    }()
}
struct-BugDemo:View{
var body:一些观点{
导航视图{
NavigationLink(“转到子对象”,目标:child())
}
}
}
结构子级:视图{
@国家私有变量日期:日期=日期()
var body:一些观点{
文本(DateFormatter.localizedString(起始:日期,日期样式:.medium,时间样式:.medium))
.navigationBarTitle(“儿童”)
.onReceive(PublisherHolder.shared.publisher){
打印(“Child.onReceive”)
self.date=$0
}
翁迪萨佩尔先生{
打印(“Child.onDisappear”)
}
}
}
私有类发布者文件夹{
静态let shared=PublisherHolder()
lazy-var-publisher:AnyPublisher={
Timer.publish(每隔:1,在:.main上,在:.default中)
.自动连接()
.print()
.删除任何发布者()
}()
}

这不是
.onReceive
。这是
NavigationView
行为。不管幸运与否,它缓存了导航堆栈以供可能的重用

如果您改为使用下面的show/hide for
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())
//            }
    }