首页 > 解决方案 > @Published 属性在用作导航栏的标题时有延迟

问题描述

我刚刚注意到,当使用@Published属性作为导航的标题时,显示值时会有一些延迟(但如果在 ViewModel 的初始化上进行订阅,它会立即显示),而且延迟仅在导航栏上,因为Text视图立即显示值:

class ContentViewModel: ObservableObject {
    @Published var text: String = ""
    private var cancellables = Set<AnyCancellable>()

    func onAppear() {
        Just("onAppear text")
            .sink { [weak self] in
                self?.text = $0
            }
            .store(in: &cancellables)
    }
}

struct ContentView: View {
    @ObservedObject var viewModel: ContentViewModel

    var body: some View {
        Text(viewModel.text)
            .padding()
            .navigationTitle(viewModel.text)
            .onAppear(perform: viewModel.onAppear)
    }
}

struct MainView: View {
    @StateObject var viewModel = ContentViewModel()

    var body: some View {
        NavigationView {
            NavigationLink("Open View") {
                ContentView(viewModel: viewModel)
            }
        }
    }
}

注意:使用工具栏还可以立即显示标题:

.toolbar(content: {
    ToolbarItemGroup(placement: .principal) {
       Text(viewModel.text)
           .fixedSize()
    }
})

注意:但我对工具栏的小缺点是文本没有被截断,如果我有一个长文本(因为在我的真实应用程序中可以是动态的)溢出并显示在前导/尾随按钮下方。可能与fixedSize()(但如果我不申请,视图不可见,看起来没有正确的布局更新)

标签: iosswiftswiftuiswiftui-navigationview

解决方案


实际上存在滞后,但您可以使用 init 而不是 onAppear 来加载人员:

class ContentViewModel: ObservableObject {
    @Published var text: String = ""
    private var cancellables = Set<AnyCancellable>()

    init() { // THIS
        Just("onAppear text")
            .sink { [weak self] in
                self?.text = $0
            }
            .store(in: &cancellables)
    }
}

struct TheView: View {
    @ObservedObject var viewModel: ContentViewModel

    var body: some View {
        Text(viewModel.text)
            .padding()
            .navigationTitle(viewModel.text)
            //.onAppear(perform: viewModel.onAppear) THIS
    }
}

推荐阅读