从层次结构中删除视图时,View.onReceive不会取消订阅

时间:2020-04-12 12:20:17

标签: swiftui combine

在该视图消失之后,似乎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()
    }()
}

1 个答案:

答案 0 :(得分:1)

这不是.onReceive。这是NavigationView的行为。不管是否幸运,它都会缓存导航堆栈以备将来重用。

如果您对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())
//            }
    }