Home > database >  Find a uiviewcontroller from uinavigationcontroller
Find a uiviewcontroller from uinavigationcontroller

Time:09-22

I am trying to figure out a generic way to find a uiviewcontroller which is auto type casted. Currently, I do have this.

extension UINavigationController {

    func contoller(ofType type:AnyClass) -> UIViewController? {
        for controller in self.viewControllers {
            if controller.isKind(of: type) {
                return controller
            }
        }
        return nil
    }
}

Calling will be like:

if let controller = self.navigationController?.contoller(ofType: MyController.self) as? MyController{}

That's how I am able to get controller object and I need to type cast it also. I am trying to figure out a way to do this like as:

if let controller:MyController = self.navigationController?.contoller(ofType: MyController.self){}

So that I will not need to do any type casting.

For this, I may need to do some changes in UINavigationController extension function. Need some suggestion for this.

CodePudding user response:

Use Generics:

extension UINavigationController {
    func controller<T: UIViewController>(ofType _: T.Type) -> UIViewController? {
        for controller in viewControllers where controller is T {
            return controller
        }
        return nil
    }
}

EDIT 1: I would return also the VC as type we requested.

And recommend to use first in the name, cause there might be more than one. And you might want to introduce lastController(as:) in the future

extension UINavigationController {
    func firstController<T: UIViewController>(as _: T.Type) -> T? {
        for case let controller as T in viewControllers {
            return controller
        }
        return nil
    }
}

Then usage could be:

let nav = UINavigationController()
nav.viewControllers = [UIViewController(), UITabBarController()]
let tabVC = nav.firstController(as: UITabBarController.self)

EDIT 2: You can shorten the extension body:

extension UINavigationController {
    func firstController<T: UIViewController>(as _: T.Type) -> T? {
        viewControllers.first(where: { $0 is T }) as? T
    }
}
  • Related