Search code examples
iosswiftclasstypesparameters

Pass an array of types as function param and check if a concrete object inherits any type from array in Swift?


In my particular case I need to get the topmost view controller but avoid view controllers of some types like UIAlertController. I took code from here:

extension UIViewController {
    func topMostViewController() -> UIViewController {

        if let presented = self.presentedViewController {
            return presented.topMostViewController()
        }

        if let navigation = self as? UINavigationController {
            return navigation.visibleViewController?.topMostViewController() ?? navigation
        }

        if let tab = self as? UITabBarController {
            return tab.selectedViewController?.topMostViewController() ?? tab
    }

        return self
    }
}

I need somehow pass array of types into this method and for example return self if presentedViewController is UIAlertController. But could you explain how to do that? Tried to pass arrays of types [UIViewController.self], [AnyClass] and etc. but I'm not able to check for a concrete type.


Solution

  • Since UIViewController is an Objective-C class, you can use isKind(of:) to check if an view controller is an instance of a particular UIViewController.Type.

    If I understand what you want to do correctly,

    extension UIViewController {
        func topMostViewController(typesToAvoid: [UIViewController.Type]) -> UIViewController {
    
            if let presented = self.presentedViewController {
                if typesToAvoid.contains(where: presented.isKind(of:)) {
                    return self
                }
                return presented.topMostViewController(typesToAvoid: typesToAvoid)
            }
    
            if let navigation = self as? UINavigationController {
                return navigation.visibleViewController?.topMostViewController(typesToAvoid: typesToAvoid) ?? navigation
            }
    
            if let tab = self as? UITabBarController {
                return tab.selectedViewController?.topMostViewController(typesToAvoid: typesToAvoid) ?? tab
            }
            return self
        }
    }