Search code examples
swifterror-handlingswift3option-typeoptional-chaining

Swift3 optional chaining and unwrapping with error handling


I am attempting to unwrap an optional using the guard let syntax. The goal with guard let is to unwrap optionals, aborting the procedure if .none/nil is ever encountered.

I had thought that this meant that an optional could not be legally returned from an expression on the right-hand-side of a guard let. However, it seems if you combine two optional-producing expressions into the RHS expression, only one of those optional-producing expressions is evaluated for the purposes of the guard let. For example, the parsedResponse variable below will store an optional:

guard let parsedResponse = try? (JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String:Any]) else {
                displayError(withString: "Error parsing data as JSON")
                return
            }

The try? keyword produces an optional, as does the conditional cast operator as?. If you change either of these two operators to try! or as!, you get the expected result.

Is this the expected behavior? I had assumed that attempting to do something like this would produce behavior similar to optional chaining, and the guard let would execute the 'else' code the moment it encountered .none/nil anywhere along the execution path of the evaluation of the RHS. However, this does not appear to be the case.

What does it even mean to have an optional evaluate into a constant/variable introduced by a guard let?


Solution

  • I think if you rearrange the parens it will work.

    guard let parsedResponse = (try? JSONSerialization.jsonObject(with: data, options: .allowFragments)) as? [String:Any] else {