How a UITabBarController fit into the VIPER archit

2019-02-06 00:31发布

问题:

I am writing an application which has a TabBar based navigation. I am adopting the VIPER architecture but I am really confused with the topic of how a UITabBarController's tab changing should be implemented.

回答1:

This might be late, but it might be helpful for others. My use case was to implement the tabBarController after the login screen. There can be many ways we can do it in VIPER but how I did it is as follows:

  1. Allocated TabBar manually, without using storyboards.
  2. Create a new WireFrame class only for TabBarWireframe presentation.
  3. Create a singleton class with one mutable array which will contain all the view controllers to be assigned to the tabBarController.
  4. Create a json file which will provide me the values of tabs, This step can be skipped as I wanted tabs to be dynamic based on value from JSON file. If u have static tabs skip this step.
  5. In TabBarWireframe, put a loop which call all your tabs wireframes.
  6. In your individual wireframes just instantiate the viewController obj and add it to the singleton class array we created in step 3.
  7. After all viewController which are part of tabs are part of the array. Just present the tabBar Controller from the loginviewcontroller instance(Its instance just pass through a method to the tabBarWireframe class).

Hope I made sense.



回答2:

Another way to implement UITabBarController with VIPER architecture is to provide a TabBarInterface

import Foundation
import UIKit

protocol TabBarInterface {
    func configuredViewController() -> UIViewController
}

So that each wireframe that presents a view controller in the tab bar controller implements TabBarInterface and then installIntoWindow just loops through all the wireframes calling configuredViewController for each wireframe it will present.

import Foundation

import UIKit

class TabBarWireframe : NSObject {

    let wireFrames:[TabBarInterface]
    var rootWireframe : RootWireframe?

    init(_ wireFrames:TabBarInterface...) {
        self.wireFrames = wireFrames
        super.init()
    }

    private override init() {
        self.wireFrames = [TabBarInterface]()
    }

    func installIntoWindow(window: UIWindow) {
        let tabBarController = MainTabBarController()

        var viewControllers = [UIViewController]()

        for wireFrame in wireFrames {
            viewControllers.append(wireFrame.configuredViewController())
        }

        tabBarController.viewControllers = viewControllers
        tabBarController.navigationItem.title = "Visva"

        self.rootWireframe?.installTabBarControllerIntoWindow(tabBarController: tabBarController, window: window)
    }

}

Please note that in our case RootWireframe installs the tab bar controller into the main Window, i.e:

window.rootViewController = tabBarController
window.makeKeyAndVisible()


回答3:

I'm still new to VIPER so my two cents may not be worth much but maybe have the tabbar as a private property on the AppDelegate. When you need to change to a particular index have utility methods that change the tabbar selected index but also trigger the wireframe/router creation process.