在另一个 ViewController 中的 ViewController 之间显示和切换

Displaying and switching between ViewControllers in another ViewController

我基本上是在尝试创建一个自定义的 UITabBarController,因为我需要一些特定的功能。 TabBar 本身已经完成并可以正常工作,但我不太清楚如何在此 CustomTabBarViewController 本身中显示 ViewControllers。

假设我有以下方法:

func tabSelected(_ index: Int) {}

并且通过tabbar.frame.size知道我的TabBar的高度,我如何在TabBar上方实例化两个ViewControllers并在调用tabSelected方法时在它们之间切换?过渡动画会更好,但不是必需的。

注意:我的 TabBar 不继承自 UITabBarController,仅继承自常规 UIViewController,以避免进一步混淆。

这里我创建了示例项目: CustomTabBarViewController


  • 您应该有 child ViewControllers
  • 的容器视图
  • 那么你应该有嵌入 ViewControllers
  • 的数组
  • 你应该在 CustomTabBarViewController里面改成ViewController 容器视图 ViewController 来自 VC 数组的索引,您将其作为此方法的参数传递

首先为您的 TabBar 按钮声明 outlet 集合,并获取将显示 ViewController 的容器视图的参考

@IBOutlet var tabBarButtons: [UIButton]!
@IBOutlet weak var container: UIView!

然后为您的标签栏项目创建数组

var items: [UIViewController]?

接下来为您的控制器创建惰性变量

private lazy var aVC: A = {
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    return storyboard.instantiateViewController(withIdentifier: "a") as! A
}()

private lazy var bVC: B = {
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    return storyboard.instantiateViewController(withIdentifier: "b") as! B
}()

... 这可以通过创建方法来简化,其中 returns ViewController 取决于 VC 的标识符

之后,将 ViewControllers 附加到您的 items 数组,并将每个添加为 TabBarViewController

child
override func viewDidLoad() {
    super.viewDidLoad()
    items = [aVC, bVC]
    items!.forEach { addChild([=13=]) }
}

继续声明设置方法ViewController

private func setViewController(_ viewController: UIViewController) {
    items!.forEach { [=14=].view.removeFromSuperview(); [=14=].willMove(toParent: nil) }
    container.addSubview(viewController.view)
    viewController.view.frame = container.bounds
    viewController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
    viewController.didMove(toParent: self)
}

现在为您的标签栏按钮添加操作并获取按钮索引。然后用这个索引调用你的 tabSelected 方法

@IBAction func buttonPressed(_ sender: UIButton) {
    if let index = tabBarButtons.index(of: sender) {
        tabSelected(index)
    }
}

tabSelected 中根据发件人标签栏按钮的索引从 items 设置 VC

func tabSelected(_ index: Int) {
    if let item = items?[index] {
        setViewController(item)
    }
}

终于在viewDidLoad设置第一项

override func viewDidLoad() {
    ...
    tabSelected(0)
}

现在您可以完全自定义 ViewController 并制作您从 UITabBarController

了解到的其他史诗般的东西

这是另一种方法:

1. 在你的 CustomTabBarViewController 中定义一个数组来保存 ViewControllers:

var viewControllers: [UIViewController]

实例化视图控制器并将它们添加到数组中:

// If you're not using storyboard:
let homeViewController = HomeViewController()
// If using storyboard:
let searchViewController = storyboard.instantiateViewController(withIdentifier: "SearchViewController")

viewControllers = [homeViewController, searchViewController, ...]

2.定义一个变量来跟踪选中的选项卡按钮:

var selectedIndex: Int = 0

3. 像这样实现您的 tabSelected 方法。我已经在代码中解释了每一行:

func tabSelected(_ index: Int) {
    let previousIndex = selectedIndex

    selectedIndex = index

    // Use previousIndex to access the previous ViewController from the viewControllers array.
    let previousVC = viewControllers[previousIndex]

    // Remove the previous ViewController
    previousVC.willMove(toParentViewController: nil)
    previousVC.view.removeFromSuperview()
    previousVC.removeFromParentViewController()

    // Use the selectedIndex to access the current ViewController from the viewControllers array.
    let vc = viewControllers[selectedIndex]

    // Add the new ViewController (Calls the viewWillAppear method of the ViewController you are adding)
    addChildViewController(vc)
    vc.view.frame = contentView.bounds

    // contentView is the main view above your tab buttons
    contentView.addSubview(vc.view)

    // Call the viewDidAppear method of the ViewController you are adding using didMove(toParentViewController: self)
    vc.didMove(toParentViewController: self)
}