在标签栏中重新加载当前视图控制器

Posted

技术标签:

【中文标题】在标签栏中重新加载当前视图控制器【英文标题】:Reload a current viewcontroller in tab bar 【发布时间】:2020-04-15 20:59:31 【问题描述】:

目前我有一个视图控制器,当您点击索引 3 处的选项卡(地图选项卡)时,它会加载一个包含地图(地图 A)的视图控制器。 注意:每次按下地图选项卡时,它都应该加载地图 A。 在主选项卡上的索引 0 处有一个chiclet,点击它可以让您从地图 A 切换到地图 B,然后获取你到那个地图(这个开关是手动完成的,所以使用标签栏的 selectedIndex 将标签栏保持在屏幕上,这意味着 viewWillAppear() 似乎没有被调用)。 注意:地图 A 和地图 B 共享相同的 viewController,bool 用于区分要在 viewWillAppear 中加载哪个。。我遇到的问题是在按下chiclet 从地图 A 切换之后到地图 B,一旦我在选项卡栏上再次点击地图选项卡,它会自动加载我刚刚在 (地图 B) 上的当前地图,但如前所述,当从选项卡栏按下时,它应该只加载地图 A。

这是我正在尝试的,但在按下选项卡后它仍然不会显示正确的地图:

class MainTabBarController: UITabBarController 

 func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) 
        switch viewController 
case is MapViewController:
            let nc = NotificationCenter.default
            nc.post(name: Notification.Name("changeMapStatus"), object: nil)


类 MapViewController: BaseViewController

    var mapBSelected: Bool = false

    override func viewWillAppear(_ animated: Bool) 
        super.viewWillAppear(animated)

        mapBSelected ? setupMapB() : setupMapA()


    @objc func changeMapStatus() 
          guard let mainTabController = tabBarController as? MainTabBarController else  return 
              mainTabController.refreshMapTab()
        self.MapBSelected = false
    

   func refreshMapTab() 
             let index = PrimaryFeatureTab.map.displayOrder// enum to determine tab order
              DispatchQueue.main.async 
                      self.viewControllers?.remove(at: index)
                      self.viewControllers?.insert(PrimaryFeatureTab.map.rootViewController, at: index)
                  
        

【问题讨论】:

当用户离开MapTab 时,您最好处理一下。在您的 `MapViewController' 类中实现 viewWillDisappearviewDidDisappear 并将地图和选择器重置为“A”状态。在自定义标签栏控制器中不需要任何东西。 【参考方案1】:

您可以执行以下操作


像这样在 FirstViewController 中创建一个闭包:

enum MapType 
    case mapA
    case mapB


class MainViewController: UIViewController 

    var mapSelectionClosure: ((MapType) -> Void)?

    override func viewDidLoad() 
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    

    @IBAction func aTapped(_ sender: Any) 
        mapSelectionClosure?(.mapA)
    

    @IBAction func bTapped(_ sender: Any) 
        mapSelectionClosure?(.mapB)
    


然后你可以像这样在你的 MainTabBarController 中设置这个闭包

class MainTabBarController: UITabBarController 

    override func viewDidLoad() 
        super.viewDidLoad()

        guard let mainViewController = viewControllers?.first(where:  $0 is MainViewController ) as? MainViewController else 
            return
        
        mainViewController.mapSelectionClosure =  mapType in
            self.setMapType(mapType)
        

    

    func setMapType(_ type: MapType) 
        guard let mapViewController = viewControllers?.first(where:  $0 is MapViewController ) as? MapViewController else 
            return
        
        mapViewController.selectedMapType = type
    


【讨论】:

这很好,但设置有点不同,到达地图 A 的唯一方法是通过标签栏,因此不使用 iIBAction。 IBAction 只是一个例子,它并没有切换标签!它调用闭包通知 MainTabBarController 然后 MainTabBarController 通知 MapViewController 好吧,但是如果在MainTabBarController上调用viewDidLoad后地图发生了变化,怎么知道要设置地图类型呢? 如果你从 MainViewController 调用 mapSelectionClosure?(.mapB),闭包体将再次执行 但是到达地图 A 的唯一方法是通过点击而不是在 viewController 中的标签栏。所以你会在标签栏标签被按下后调用 MainViewController 上的闭包?【参考方案2】:

MapViewController...

class MapViewController: BaseViewController 

    override func viewWillDisappear(_ animated: Bool) 
        super.viewWillDisappear(animated)
        self.setupMapA()
    


现在,当您离开地图选项卡时,它会自行重置为地图 A。

自定义 TabBarController 中无需任何代码。

【讨论】:

以上是关于在标签栏中重新加载当前视图控制器的主要内容,如果未能解决你的问题,请参考以下文章

如何在swift 3中从标签栏移动时重新加载页面?

在标签栏中的同一标签上切换视图而不使用导航控制器

无法在标签栏控制器中重新加载表格视图

使用标签栏从另一个视图返回时如何重新加载视图控制器

使用标签栏控制器离开视图时如何关闭视图

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