【问题标题】:View.onReceive doesn't cancel subscription when the view removed from hierarchy当视图从层次结构中删除时,View.onReceive 不会取消订阅
【发布时间】:2020-04-12 12:20:17
【问题描述】:

似乎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()
    }()
}

【问题讨论】:

    标签: swiftui combine


    【解决方案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())
    //            }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-21
      • 2016-07-12
      • 2012-01-07
      • 1970-01-01
      • 2020-02-15
      • 1970-01-01
      相关资源
      最近更新 更多