1

I can't really understand how to unwrap this piece of code, I tried with if, guard and with forced unwrapping, but they all crash when the id doesn't exist. Is it possible just to make it so that it shows print() in the console and not execute any further code

    guard let historyViewController = self.storyboard?.instantiateViewController(withIdentifier: "historyViewNav") else{
        fatalError("No history view controller found ");
    }
    historyViewController.modalTransitionStyle = .flipHorizontal
    present(historyViewController, animated: true, completion: nil)
Andrey Tsarev
  • 769
  • 1
  • 8
  • 25
  • in any case, guard must be terminated by return or something similar –  Jun 10 '17 at 08:13
  • https://stackoverflow.com/questions/39929592/how-to-push-and-present-to-uiviewcontroller-programmatically-without-segue-in-io –  Jun 10 '17 at 08:17
  • May I ask a question? Why you don't set the ID? –  Jun 10 '17 at 16:16

2 Answers2

2

I am not sure if I understand what you are trying to do. Here: fatalError("No history view controller found "); you are crashing the app if the controller can not be initialized from storyboard. If you dont want the app to crash, just use print() in your else statement. If you dont want anything else to happen there you can return afterwards:

guard let historyViewController = self.storyboard?.instantiateViewController(withIdentifier: "historyViewNav") else{
    print("No history view controller found ");
    return;
}

instantiateViewController(withIdentifier: "historyViewNav") does not return nil if it fails, it raises an exception. See here: link. So your guard statement does not help. Unfortunately I am not aware of straight forward way to check this in runtime, because NSExceptions are not meant to be catchable in swift, as answered here: link

However I suggest to look into the RSwift library, so you do not have to use hardcoded strings as identifiers in your code.

nautilus
  • 76
  • 4
  • It crashes with - Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Storyboard () doesn't contain a view controller with identifier 'historyViewNav'' – Andrey Tsarev Jun 10 '17 at 08:29
  • @AndreyTsarev: have you set the ID in the storyboard? –  Jun 10 '17 at 08:30
  • https://stackoverflow.com/questions/8295471/storyboard-doesnt-contain-a-view-controller-with-identifier –  Jun 10 '17 at 08:34
  • No, I haven't. I want to check if it exists. If it exists do that and if it doesn't - do something else – Andrey Tsarev Jun 10 '17 at 08:36
  • @AndreyTsarev: do you have a corresponding class historyViewNav? –  Jun 10 '17 at 08:44
  • @3000 Nope, its just a random string – Andrey Tsarev Jun 10 '17 at 08:47
  • 2
    Ah i see. I am sorry. `instantiateViewController(withIdentifier: "historyViewNav")` does not return nil if it fails, it raises an exception. [link](https://developer.apple.com/documentation/uikit/uistoryboard/1616214-instantiateviewcontrollerwithide?preferredLanguage=occ) So your `guard` statement does not help. Unfortunately I am not aware of straight forward way to check this in runtime. However I suggest to look into the RSwift library, so you do not have to use hardcoded strings as identifiers in your code. – nautilus Jun 10 '17 at 09:22
  • @nlz: it doesn't return nil BUT: "If the specified identifier does not exist (or is nil) in the storyboard file, this method raises an exception": supposedly, if it doesn't exist it IS nil: https://developer.apple.com/documentation/uikit/uistoryboard/1616214-instantiateviewcontroller –  Jun 10 '17 at 15:22
  • @nlz: anyway, he is right, I tried do/try/catch and if the ID is not in the storyboard, the app crashes. Moreover, compiler tells there's nothing to try because instantiateViewController doesn't throw exceptions. There must be something wrong in the docs (at least). –  Jun 10 '17 at 15:57
0

This works IF you put the ID in the field:

override func viewDidAppear(_ animated: Bool) {

        if let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "myTestID") as? UIViewController
        {
            vc.modalTransitionStyle = .flipHorizontal
            present(vc, animated: true, completion: nil)
        }else{
            print("error")
        }

    }