【问题标题】:SwiftUI: Disable/Re-Enable button based on WebView stateSwiftUI:基于 WebView 状态禁用/重新启用按钮
【发布时间】:2021-02-16 22:22:19
【问题描述】:

我在WebView 周围有一个UIViewRepresentable 包装器。我在 webview 下方添加了一个带有前进和后退按钮的栏。我希望当WebViewcanGoBackcanGoForward 属性返回false 时禁用按钮,反之亦然。

ViewModel 包括:

class ViewModel: ObservableObject {
  ...
   @Published var canGoBackPublisher = CurrentValueSubject<Bool, Never>(false)
   @Published var canGoForwardPublisher = CurrentValueSubject<Bool, Never>(false)
}

ContentView 包括:

struct ContentView: View {
   @ObservedObject var viewModel = ViewModel()
   ...
   
   var body: some View {
      VStack(spacing: 0) {
         WebView(viewModel: viewModel).overlay (
            RoundedRectangle(cornerRadius: 4, style: .circular)
               .stroke(Color.gray, lineWidth: 0.5)
         )
         WebNavigationView(viewModel: viewModel)
             .frame(minWidth: 0, maxWidth: .infinity, minHeight: 64, maxHeight: 64)
             .background(Color.white)
      }
      
   }

WebNavigationView(按钮栏)包括:

struct WebNavigationView: View {
   @ObservedObject var viewModel: ViewModel
   ...      
   
   var body: some View {
      HStack(alignment: .center, spacing: 64, content: {
         Button(action: goBack) {
            Image(systemName: "chevron.left").resizable().aspectRatio(contentMode: .fit)
            }.disabled(!viewModel.canGoBackPublisher.value).
                frame(width: 24, height: 24, alignment: .center).padding(.leading, 32)
         Button(action: goForward) {
            Image(systemName: "chevron.right").resizable().aspectRatio(contentMode: .fit)
            }.disabled(!viewModel.canGoForwardPublisher.value)
                .frame(width: 24, height: 24, alignment: .center)
         Spacer()
      })
   }
   ...

WebViewdelegate 包括:

   func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
      parent.viewModel.canGoBackPublisher.send(webView.canGoBack)
      parent.viewModel.canGoForwardPublisher.send(webView.canGoForward)
   }

按钮按预期显示为灰色并禁用。但是它们不会对状态变化做出反应,即使viewModel.canGoBackPublisher.value 返回true,它们也会保持禁用状态。我是一名资深的 iOS 开发人员,但对 SwiftUI 非常、非常、非常陌生

【问题讨论】:

    标签: ios swift swiftui wkwebview


    【解决方案1】:

    通过将发布者属性定义为@Published CurrentValueSubject,您最终会加倍发布者属性。

    最简单的解决方法是将它们设为Published,它会为您处理大部分工作:

    class ViewModel: ObservableObject {
       @Published var canGoBack = false
       @Published var canGoForward = false
    }
    
    //...
    //In delegate:
    func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
      viewModel.canGoBack = webView.canGoBack
      viewModel.canGoForward = webView.canGoForward
    }
    
    //...
    //In Navigation view:
    Button(action: goBack) {
      Image(systemName: "chevron.left").resizable().aspectRatio(contentMode: .fit)
    }.disabled(!viewModel.canGoBack) //<-- here
    .frame(width: 24, height: 24, alignment: .center).padding(.leading, 32)
    
    Button(action: goForward) {
      Image(systemName: "chevron.right").resizable().aspectRatio(contentMode: .fit)
    }.disabled(!viewModel.canGoForward) //<-- here
    .frame(width: 24, height: 24, alignment: .center)
    

    如果需要,您仍然可以将它们定义为 CurrentValueSubject(并放弃 @Published 属性包装器),但在这种情况下可能不需要。

    关于@Published 和 CurrentValueSubject 之间区别的好问题:Difference between CurrentValueSubject and @Published

    【讨论】:

    • 非常感谢!我认为迷失在太多的 SO 问题和中等文章中。非常感谢!
    猜你喜欢
    • 2013-10-14
    • 2021-11-24
    • 2011-09-15
    • 2021-10-19
    • 2018-02-15
    • 2012-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多