Swift 5 - 用户第二次单击标签栏按钮后,需要帮助在视图控制器 1 上重新加载 Web 视图

Posted

技术标签:

【中文标题】Swift 5 - 用户第二次单击标签栏按钮后,需要帮助在视图控制器 1 上重新加载 Web 视图【英文标题】:Swift 5 - Need help reloading web view on view controller 1 after user clicks tab bar button for the second time 【发布时间】:2021-03-14 20:05:50 【问题描述】:

在过去的一周里,我已经被这个问题困扰了 30 多个小时,试图弄清楚这一点,但似乎无法做到这一点。我有一个 Swift 5 ios 应用程序。它有一个带有 3 个标签/视图控制器的标签栏视图控制器。我所有的代码都存储在一个视图控制器文件中。下面是标签栏和第一个视图控制器的代码,所有其他视图控制器的结构都类似。

预期:当用户在选项卡上单击两次时,我们会将他们单击的次数存储在名为 VariableRefresh 的变量中。当该变量变为 2 时,我们将刷新视图控制器上的 Web 视图。

当我为视图控制器 1 单击两次选项卡栏时,会触发调试打印消息,它告诉我两次单击选项卡栏是成功的,但 Web 视图没有刷新。我收到错误消息说 web 视图返回 nil 并使其成为可选值。所以我补充说?到网络视图使其成为可选值,但问题是网络视图仍然为零,并且它不会刷新/重新加载。当用户按两次标签栏时应该调用func reload,它应该在视图控制器1 func reload()中执行函数。

import GoogleMobileAds
import UIKit
import SwiftUI
import FBAudienceNetwork
import WebKit

//we will use this to identifiy if two click are made on this tab, we will put if then statement to monitor clicks and if 2 taps ont he tab, then we will refresh the view controller 1 webview.
var VariableRefresh = 0


//variable for url
let url1 = URL(string:"http://tesla1.social-goat.com")
//variable for url request
let request = URLRequest(url: url1!)





class TabBarClass: UITabBarController, UITabBarControllerDelegate, WKNavigationDelegate  
    
    
    override func viewDidLoad() 
        super.viewDidLoad()
        debugPrint("Message - TabBarClass - viewDidLoad")
        self.delegate = self
    

    func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) 

        let selectedIndex = tabBarController.viewControllers?.firstIndex(of: viewController)!
        if selectedIndex == 0 
          debugPrint("Message - loaded func tabBarController")
            VariableRefresh += 1
            
            if VariableRefresh == 2
            
            let sendValue = ViewController1();
            sendValue.reload()
            
            
        


        
    
    


//################  view controller 1 - Groups START
class ViewController1: UIViewController,FBAdViewDelegate
    
   
    let url1 = URL(string:"http://tesla1.social-goat.com")
    //
  
    @IBOutlet var webView1: WKWebView!
    @IBOutlet weak var bannerView_home: GADBannerView!
    
    override func viewDidLoad()
        super.viewDidLoad()
        //moved request to the parent level so that viewcontroller1 and tab bar view controller can access
      //  let request = URLRequest(url: url1!)
        debugPrint("Message - viewDidLoad")
        //load request for webview
        webView1.load(request)
        //allow webvie to have back and forward browsing function by swip left or right
        webView1.allowsBackForwardNavigationGestures = true
        webView1.navigationDelegate = self
        webView1.isUserInteractionEnabled = true
       
        
     //banner id ca-app-pub-8404457641397226/8691324688
    //test banner id ca-app-pub-3940256099942544/2435281174
    // Replace this ad unit ID with your own ad unit ID.
    bannerView_home.adUnitID = "ca-app-pub-8404457641397226/8691324688"
    bannerView_home.rootViewController = self
        
    //lets load the admob banner
        loadBannerAd()
        
       
 
        
    
    
    override func didReceiveMemoryWarning() 
        super.didReceiveMemoryWarning()
        
    
   //this will be called from tab bar view, the problem here is that webview will come up as nil. putting ? or ! still does not reload the webview.
    func reload()
        webView1.load(request)
    
    
    override func viewWillAppear(_ animated: Bool) 
        debugPrint("Viewwillapper")
        let request = URLRequest(url: url1!)
        //reload webview when you navigate back to the view controller 1 tab
        webView1.load(request)
        
        
    
    
   
  
    override func viewDidAppear(_ animated: Bool) 
      super.viewDidAppear(animated)
      // Note loadBannerAd is called in viewDidAppear as this is the first time that
      // the safe area is known. If safe area is not a concern (eg your app is locked
      // in portrait mode) the banner can be loaded in viewDidLoad.
     
    

    override func viewWillTransition(
      to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator
    ) 
      coordinator.animate(alongsideTransition:  _ in
        self.loadBannerAd()
      )
    

    func loadBannerAd() 

      // Here safe area is taken into account, hence the view frame is used after the
      // view has been laid out.
      let frame =  () -> CGRect in
        if #available(iOS 11.0, *) 
          return view.frame.inset(by: view.safeAreaInsets)
         else 
          return view.frame
        
      ()
      let viewWidth = frame.size.width

      // Here the current interface orientation is used. If the ad is being preloaded
      // for a future orientation change or different orientation, the function for the
      // relevant orientation should be used.
      bannerView_home.adSize = GADCurrentOrientationAnchoredAdaptiveBannerAdSizeWithWidth(viewWidth)

      bannerView_home.load(GADRequest())
    
    



//################  view controller 1 - Groups END

【问题讨论】:

【参考方案1】:

当你调用 let sendValue = ViewController1();您创建了与您的实现断开连接的视图控制器的全新实例。尝试替换 let sendValue = ViewController1();让 sendValue = tabBarController.viewControllers[0] 作为 ViewController1!在您的标签栏控制器类中。然后你应该可以调用 sendValue.reload()。我第一次尝试从不同的类调用 reload 时错过了。

【讨论】:

您好,Marko,感谢您的回复。我将 func reload() webView1.load(request) 替换为 With func reload() webView1.load(request) webView1.allowsBackForwardNavigationGestures = true webView1.navigationDelegate = self webView1.isUserInteractionEnabled = true 而且我仍然得到一个 nil 错误“致命错误:意外发现 nil同时为 webView.load(request) 隐式展开 Optional"。我想要做的是当用户单击选项卡按钮两次时,它将重新加载 web 视图。我想用我的 3 个选项卡按钮中的每一个来执行此操作,如果用户在第一个选项卡上,然后按两次选项卡 1,那么它应该重新加载 webview。 我正在重读你的答案,所以你是说我应该直接从标签栏控制器类调用 webView1.load(request) 吗?如果是这样,我将如何做到这一点,因为 Web 视图位于视图控制器 1 类上。我试图在标签栏类上创建一个 IB 连接,但是当我从视图控制器 1 上的 Web 视图中拖动一个连接并尝试将其拖到标签栏类时,它不会让我在标签栏类中删除 Web 视图的连接。 我现在将您的代码复制/粘贴到代码编辑器中,以便更清楚地看到您想要实现的目标。当您调用let sendValue = ViewController1(); 时,您将创建与您的实现断开连接的视图控制器的全新实例。尝试在标签栏控制器类中将let sendValue = ViewController1(); 替换为let sendValue = tabBarController.viewControllers[0] as ViewController1!。然后你应该可以打电话给sendValue.reload()。我第一次错过了你尝试从不同的类调用 reload。 天啊谢谢谢谢MARKO!!!!你是最好的!对不起,我很兴奋地喊出你为我工作,更重要的是,你让我学到了一些关于“创建的 viewcontroller1 的新实例”的新知识。我从来不知道会发生这种情况,现在我正在对此进行更多研究。非常感谢再次感谢!!干杯! :)

以上是关于Swift 5 - 用户第二次单击标签栏按钮后,需要帮助在视图控制器 1 上重新加载 Web 视图的主要内容,如果未能解决你的问题,请参考以下文章

关闭块不会在第二次 swift3 上重新加载表

在第二次按下时更改标签栏按钮的行为

我们如何在 Swift 中单击第一个 VC 时打开标签栏

第二视图中的标签栏

如何在c#中实现单击一个按钮后,再在窗体内点击一次鼠标,把该按钮移动到第二次点击的位置?

无法制作双向按钮(第一次单击使问题在第二次启用时禁用)