web-dev-qa-db-ja.com

UITabBarControllerでコーディネーターを使用するにはどうすればよいですか?

MVVM-Cアーキテクチャで遊んでいますが、タブが選択されたときに異なるタブで複数のコーディネーターをインスタンス化する方法がわかりません。

メインのアプリコーディネータークラスは次のとおりです...

protocol UINavigationControllerType: class {
func pushViewController(_ viewController: UIViewController, animated: Bool)
func popViewController(animated: Bool) -> UIViewController?
}

protocol Coordinator: class {
func start()
}

final class AppCoordinator: Coordinator {
// MARK: - Properties
var managedObjectContext: NSManagedObjectContext!
var coordinators = [String : Coordinator]()

var tabController: UITabBarController?

// MARK: - Object Lifecycle
init(moc: NSManagedObjectContext, tabController: UITabBarController) {
    self.managedObjectContext = moc
    self.tabController = tabController
}

// MARK: - Coordinator
func start() {
    guard let tabController = tabController else {return}

    let profileNavigationController = NavigationController()
    profileNavigationController.tabBarItem = UITabBarItem(title: "Profile", image: UIImage(named: "profileUnselected"), selectedImage: UIImage(named: "profileSelected"))

    let plansNavigationController = NavigationController()
    plansNavigationController.tabBarItem = UITabBarItem(title: "Plans", image: UIImage(named: "plansUnselected"), selectedImage: UIImage(named: "plansSelected"))

    tabController.viewControllers = [profileNavigationController, plansNavigationController]
    tabController.selectedViewController = profileNavigationController

    let profileCoordinator = ProfileCoordinator(navigationController: profileNavigationController)
    profileCoordinator.managedObjectContext = managedObjectContext
    coordinators["profileCoordinator"] = profileCoordinator
    profileCoordinator.delegate = self
    profileCoordinator.start()
}
}

// MARK: - ProfileCoordinatorDelegate
extension AppCoordinator: ProfileCoordinatorDelegate {}

では、タブが選択されているときに、現在のコーディネーター(ProfileCoordinator)からPlansCoordinatorにどのように移動しますか?

21
Luke97

私のコーディネーターの構造はあなたのものとは異なりますが、あなたに役立つかもしれません。私の場合、コーディネータープロトコルには、そのコーディネーターのViewControllerを指すrootViewControllerプロパティがあります。

その後、私のAppCoordinatorTabCoordinatorを永続化しますが、これは次のようになります(実際のコードでは、永続化されたコーディネーターはNavigationCoordinatorsであり、NavigationControllersを保持する特別なコーディネーターです。例ViewControllerを追加し、メモリ管理機能を削除してわかりやすくしました。)

final class TabCoordinator: NSObject, Coordinator {

var rootViewController: UIViewController {
    return tabController
}

let tabController: UITabBarController

let homeCoordinator: HomeCoordinator
let historyCoordinator: HistoryCoordinator
let profileCoordinator: ProfileCoordinator

var coordinators: [Coordinator] {
    return [homeCoordinator, historyCoordinator, profileCoordinator]
}

init(client: HTTPClient, persistence: Persistence) {

    tabController = UITabBarController()

    homeCoordinator = HomeCoordinator(client: client, persistence: persistence)

    historyCoordinator = HistoryCoordinator(client: client, persistence: persistence)

    profileCoordinator = ProfileCoordinator(client: client, persistence: persistence)

    var controllers: [UIViewController] = []

    let homeViewController = homeCoordinator.rootViewController
    homeViewController.tabBarItem = UITabBarItem(title: Localization.homeTab.string, image: Asset.iconMenuRecharge.image, selectedImage: Asset.iconMenuRechargeActivated.image)

    let historyViewController = historyCoordinator.rootViewController
    historyViewController.tabBarItem = UITabBarItem(title: Localization.walletTab.string, image: Asset.iconMenuWallet.image, selectedImage: Asset.iconMenuWalletActivated.image)

    let profileViewController = profileCoordinator.rootViewController
    profileViewController.tabBarItem = UITabBarItem(title: Localization.profileTab.string, image: Asset.iconMenuProfile.image, selectedImage: Asset.iconMenuProfileActivated.image)

    super.init()

    controllers.append(homeViewController)
    controllers.append(historyViewController)
    controllers.append(profileViewController)

    tabController.viewControllers = controllers
    tabController.tabBar.isTranslucent = false
    tabController.delegate = self

}
}

したがって、基本的に、TabBarControllerはrootViewControllerがTabBarControllerであるTabCoordinatorです。 TabCoordinatorは関連するCoordinatorをインスタンス化し、それぞれのrootViewControllersをタブに追加します。

NavigationCoordinatorの基本的な実装は次のとおりです。

class NavigationCoordinator: NSObject, Coordinator {    

    public var navigationController: UINavigationController     

    public override init() {
        self.navigationController = UINavigationController()
        self.navigationController.view.backgroundColor = .white
        super.init()
    }    

    public var rootViewController: UIViewController {
        return navigationController
    }
}

Coordinatorの基本バージョン:

public protocol Coordinator: class {    
    var rootViewController: UIViewController { get }    
}
26
Bruno Rocha

この質問の例を共有したいと思います。私のアプローチは少し異なり、TabCoordinatorは彼の体にすべてを含んでいません。これの代わりに、すべてのコーディネーターはコントローラーと関係を持ち、すべてのUIViewController(Tabbarコントローラー内)には委任パターンのようなUITabBarController参照があります。

class Coordinator {

    var navigationController: UINavigationController?
    var childCoordinators: [Coordinator] = [Coordinator]()

    init(with navigation: UINavigationController) {
        self.navigationController = navigation
    }

    func start() {}

}

次に、コーディネーターがいます。

ホームコーディネーター

final class HomeCoordinator: Coordinator {

    var currentController: HomeController?
    weak var tabController: TabController?


    override init(with navigation: UINavigationController) {
        super.init(with: navigation)

        currentController = HomeController()
        currentController?.coordinator = self
        childCoordinators.append(self)
    }

    override func start() {

        navigationController?.pushViewController(currentController ?? UIViewController(),
                                                 animated: true)

    }

    public func getHomeData() {

        // GETTING HOME DATA

        tabController?.requestFromHomeController()

    }

}

コーディネーターについて

final class AboutCoordinator: Coordinator {

    var currentController: AboutController?
    weak var tabController: TabController?

    override init(with navigation: UINavigationController) {
        super.init(with: navigation)

        currentController = AboutController()
        currentController?.coordinator = self
        childCoordinators.append(self)
    }


    override func start() {

        navigationController?.pushViewController(currentController ?? UIViewController(),
                                                 animated: true)

    }

    public func getAboutData() {

        // GETTING ABOUT DATA

        tabController?.requestFromAboutController()

    }
}

UITabBarController

final class TabController: UITabBarController {

    weak var coordinator: MainTabCoordinator?


    override func viewDidLoad() {
        super.viewDidLoad()


        let navigationController1 = UINavigationController()
        let coordinator1 = HomeCoordinator(with: navigationController1)
        coordinator1.tabController = self
        coordinator1.currentController?.tabBarItem = UITabBarItem(title: "HOME",
                                                                  image: nil,
                                                                  tag: 11)

        let navigationController2 = UINavigationController()
        let coordinator2 = AboutCoordinator(with: navigationController2)
        coordinator2.tabController = self
        coordinator2.currentController?.tabBarItem = UITabBarItem(title: "ABOUT",
                                                                  image: nil,
                                                                  tag: 22)


        viewControllers = [
            coordinator1.currentController!,
            coordinator2.currentController!
        ]

        tabBar.barTintColor = UIColor.white
        tabBar.isTranslucent = false

    }

    public func requestFromHomeController() {
        print("Home Triggered the function")

        coordinator?.fetchHome(with: "Simple Data",
                               completion: { (dictionary, error) in
                                print("dict from home -> ", dictionary)
        })



    }

    public func requestFromAboutController() {
        print("About Triggered the function")

        coordinator?.handleAbout(with: "Simple Data",
                                 completion: { (dictionary, error) in
                                    print("dict from about -> ", dictionary)
        })
    }    
}

AppDelegateからアプリを準備する

in application(_ application:UIApplication、didFinishLaunchingWithOptions関数

let appNavigationController = UINavigationController()
let tabCoordinator = MainTabCoordinator(with: appNavigationController ?? UINavigationController())
tabCoordinator.start()
window?.rootViewController = appNavigationController

これがAboutControllerです

final class AboutController: UIViewController{

    weak var coordinator: AboutCoordinator?

    // define a button and add its target to handleButton function

    @objc private func handleButton(_ sender: UIButton) {

        coordinator?.getAboutData()
    }


    override func viewDidLoad() {
        super.viewDidLoad()

        // ui settings
    }
}

MainTabCoordinator

final class MainTabCoordinator: Coordinator {

    var currentController: TabController?


    override init(with navigation: UINavigationController) {
        super.init(with: navigation)

        self.currentController = TabController()
        self.childCoordinators.append(self)
        currentController?.coordinator = self
    }



    override func start() {

        navigationController?.pushViewController(currentController ?? UIViewController(),
                                                 animated: true)

    }

    func fetchHome(with title: String, completion:  @escaping (_ result: Dictionary<String,Any>, _ error: NSError?) -> ()) {

        completion(["ss":"ss"], nil)

    }


    func handleAbout(with title: String, completion: @escaping (_ result: Dictionary<String,Any>, _ error: NSError?) -> ()) {

        completion(["ss":"ss"], nil)
    }

}

作業スキーマは次のようになります。

AboutController --->トリガーされたアクション---> AboutCoordinator ---> TabBarController referenceは、アクションについてのリクエストがあります----> MainTabCoordinatorハンドルが機能します。

1
elia