40

I'm migrating my code over to Swift 3 and see a bunch of the same warnings with my do/try/catch blocks. I want to check if an assignment doesn't return nil and then print something out to the console if it doesn't work. The catch block says it "is unreachable because no errors are thrown in 'do' block". I would want to catch all errors with one catch block.

let xmlString: String?
    do{
        //Warning for line below: "no calls to throwing function occurs within 'try' expression
        try xmlString = String(contentsOfURL: accessURL, encoding: String.Encoding.utf8)

        var xmlDict = XMLDictionaryParser.sharedInstance().dictionary(with: xmlString)
        if let models = xmlDict?["Cygnet"] {
            self.cygnets = models as! NSArray
        }

    //Warning for line below: "catch block is unreachable because no errors are thrown in 'do' block
    } catch {
        print("error getting xml string")
    }

How would I write a proper try catch block that would handle assignment errors?

Bleep
  • 431
  • 1
  • 4
  • 8
  • Actually the `try` must be written right before the throwing method rather than before the variable which contains the result - `xmlString = try String(...` but does that method really **throw** an error in Swift 3? – vadian Aug 08 '16 at 17:55
  • The only thing is if it returns an assignment of nil. Why would the catch block still be unreachable though? – Bleep Aug 08 '16 at 18:03
  • 2
    A `do - catch` block requires at least one method which throws an error. `String(contentsOfURL:` doesn't seem to do so. By the way: I doubt that `String(contentsOfURL:` will compile in Swift 3 – vadian Aug 08 '16 at 18:04
  • would an if (xmlString != nil) be a better check for assignment then? – Bleep Aug 08 '16 at 18:07
  • 1
    Please read the documentation matching the Xcode version you are using to figure out the proper syntax. The method signatures in the Swift 3 betas can differ dramatically. – vadian Aug 08 '16 at 18:23
  • `try xmlString = String(contentsOf: url, encoding: String.Encoding.utf8)` in Swift 3 (Xcode Beta 4) – Willjay Aug 09 '16 at 02:05
  • Why does it require to have explicit code that throws an error in order be caught by catch block? Why any exception in do block don't end up in catch block with default system error? – Delorean Nov 23 '16 at 23:39

1 Answers1

67

One way you can do is throwing your own errors on finding nil.

With having this sort of your own error:

enum MyError: Error {
    case FoundNil(String)
}

You can write something like this:

    do{
        let xmlString = try String(contentsOf: accessURL, encoding: String.Encoding.utf8)
        guard let xmlDict = XMLDictionaryParser.sharedInstance().dictionary(with: xmlString) else {
            throw MyError.FoundNil("xmlDict")
        }
        guard let models = xmlDict["Cygnet"] as? NSArray else {
            throw MyError.FoundNil("models")
        }
        self.cygnets = models
    } catch {
        print("error getting xml string: \(error)")
    }
OOPer
  • 47,149
  • 6
  • 107
  • 142
  • 32
    +1 for demonstrating that in a catch that "error" doesn't need to match a pattern, the identifier called "error" is just defined automatically. – Kaydell Aug 28 '16 at 01:40
  • You also can try this: `var error:NSError? = nil do{ try //your method that throws Error }catch let fetchError as NSError{ error = fetchError //Play with the returned error }` – Torongo Aug 20 '17 at 04:52
  • @NaGibToroNgo, do you understand that the OP is asking how to handle `nil` checking in do-try-catch? Your code does not contain anything about `nil` checking. – OOPer Aug 20 '17 at 05:07