Mahesh NFC
Mahesh NFC

Reputation: 99

How to check View controller is available with specified identifier or not

In my application identifiers coming from the server and we are using them as view controller identifiers. Here I would like to check whether the ViewController with a specified identifier available or not. If available then only push to that controller otherwise just return. I have written code as below.

let identifier = Constants.menuSections[indexPath.section-1][indexPath.row-1]

if let vc1 = (self.storyboard?.instantiateViewController(withIdentifier:identifier)){
    let navi = BaseNaviViewController(rootViewController:vc1)
    navi.navigationBar.tintColor = .white
    navi.navigationBar.titleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.white]
    sideMenuController?.embed(centerViewController:navi, cacheIdentifier:identifier)

}else {
    return
}

Here I'm getting an error saying

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Storyboard () doesn't contain a view controller with identifier 'abc''

Upvotes: 0

Views: 973

Answers (4)

Mahesh NFC
Mahesh NFC

Reputation: 99

Finally, I got a solution

extension UIStoryboard {
    func instantiateVC(withIdentifier identifier: String) -> UIViewController? {
        // "identifierToNibNameMap" – dont change it. It is a key for searching IDs 
        if let identifiersList = self.value(forKey: "identifierToNibNameMap") as? [String: Any] {
            if identifiersList[identifier] != nil {
                return self.instantiateViewController(withIdentifier: identifier)
            }
        }
        return nil
    }
}

And I have used this method like below

let identifier = Constants.menuSections[indexPath.section-1][indexPath.row-1]

 if let viewController = UIStoryboard(name: "Main", bundle: nil).instantiateVC(withIdentifier: identifier) {
          let navi = BaseNaviViewController(rootViewController:viewController)
                 navi.navigationBar.tintColor = .white
                 navi.navigationBar.titleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.white]
                 sideMenuController?.embed(centerViewController:navi, cacheIdentifier:identifier)
        }
        else {

            ServerService.ShowAlertMessage(ErrorMessage: "No controller Available", title: "Oops . . . !", view: self)
        }

Upvotes: 2

Hitesh Surani
Hitesh Surani

Reputation: 13577

If I am not wrong, You’re trying to achieve dynamic screen redirection as per storyboard identifier and You get storyboard_id from Array.

Earlier, I have worked with the same kind of requirements and also suffering from the same issue. Unfortunately, there is no solution to stop to crash if storyboard_id not exist.

At that time, I have added an empty storyboard_id if destination ViewController is not available, Before redirection, I was checked if storyboard_id is empty and then Skip redirection code.

Code:

let identifier = Constants.menuSections[indexPath.section-1][indexPath.row-1]

if identifier.count == 0{
    return
}else{
    let vc1 = (self.storyboard?.instantiateViewController(withIdentifier:identifier))
    let navi = BaseNaviViewController(rootViewController:vc1)
    navi.navigationBar.tintColor = .white
    navi.navigationBar.titleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.white]
    sideMenuController?.embed(centerViewController:navi, cacheIdentifier:identifier)
}

Thanks

Upvotes: 0

Anil.khanna89
Anil.khanna89

Reputation: 21

This method will return nil if the identifier doesn't exist, so just check for that with an NSAssert.

Upvotes: 0

Lal Krishna
Lal Krishna

Reputation: 16200

You can store all the identifiers in enum like this:

enum Identifier: String {
    case viewcontroller

    var storyboardName: String {
        switch self {
        case .viewcontroller : return "Main"
        }
    }
}

if let validIdentifier = Identifier(rawValue: "vc") {
    let storyboard = UIStoryboard(name: validIdentifier.storyboardName, bundle: nil)
    let vc = storyboard.instantiateViewController(withIdentifier: validIdentifier.rawValue)
}

Upvotes: -1

Related Questions