4

My understanding of try? was that when the expression following try? is evaluated, nil will be returned if there is an exception, otherwise the return value of the function will be returned.

When I run the following code:

guard let istream = InputStream(url: url),
      let ambiguousObj = try? JSONSerialization.jsonObject(with: istream, options: []),
      let jsonObj = ambiguousObj as? [[String: Any]] else {
    throw ExportError.recoveredParseFailed
}

I get an error pertaining to the second line above:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** +[NSJSONSerialization JSONObjectWithStream:options:error:]: stream is not open for reading'

I understand how to fix the error. (I needed to call istream.open())

But, could someone help me understand why try? didn't catch the exception in this case?

Josh Sherick
  • 2,081
  • 3
  • 20
  • 35

1 Answers1

4

try? evaluates the expression and returns nil if a Swift error is thrown during the evaluation. In your situation, the Foundation library throws an Objective-C NSException, as can be seen if you set an exception breakpoint:

(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x00007fffbe5cb45d libobjc.A.dylib`objc_exception_throw
    frame #1: 0x00007fffa9855c3d CoreFoundation`+[NSException raise:format:] + 205
    frame #2: 0x00007fffab3a001a Foundation`+[NSJSONSerialization JSONObjectWithStream:options:error:] + 178

Objective-C exceptions cannot be catched in Swift (unless you use an Objective-C wrapper, see for example Catching NSException in Swift).

Community
  • 1
  • 1
Martin R
  • 488,667
  • 78
  • 1,132
  • 1,248