0

I'm new to Swift 2.0 programming (coming from the world of C#), and I'm simply trying to write a function to parse some data from a string and return the result. The function itself works well, but as part of the process, the string functions may throw and error if the input string is improperly formatted and I would like to prepare a catch-all error handler for the function to deal with this. Here's the code for the original function without error handling:

// Parses the numeric value of the BATT return string
private func parseBatteeryLevel(inputStr : String) -> Int {
    if inputStr.hasPrefix("BATT") && inputStr.containsString("%") {
        let start = inputStr.startIndex.advancedBy(5)
        let end = inputStr.characters.indexOf("%")?.advancedBy(-1)

        if end != nil {
            return Int(inputStr.substringWithRange(start...end!))!
        }else{
            return 0
        }
    }else{
        printStatus("Return Value Parse Error: \"\(inputStr)\"")
        return 0
    }
}

As you can see, I did implement a basic sanity check for the strings that could be inputted but it is by no means exaustive. My primary concern is what happens if is passes the checks, but causes the advanceBy() or any of the internal string functions to fail?

I did try to wrap the code in a do-catch block as shown below,

private func parseBatteeryLevel(inputStr : String) -> Int {
    if inputStr.hasPrefix("BATT") && inputStr.containsString(" ") {
        do {
            let start = try inputStr.startIndex.advancedBy(5)
            let end = try inputStr.characters.indexOf("%")?.advancedBy(-1)

            if end != nil {
                return try Int(inputStr.substringWithRange(start...end!))!
            }else{
                return 0
            }
        } catch let error as NSError {
            printStatus(error.description)
        }
    }else{
        printStatus("Return Value Parse Error: \"\(inputStr)\"")
        return 0
    }
}

but then I get warnings, next to all the lines inside the do block, marked with the try keyword saying,

No calls to throwing functions occur within 'try' expression

Then, there is another warning next to the catch keyword saying,

'catch' block is unreachable because no errors are thrown in 'do' block

This doesn't make sense because the function clearly crashes the program if an invalid string is entered. This would be painfully simple to deal with in C# but what is the proper way to handle this in Swift 2.0?

Jason O
  • 753
  • 9
  • 28
  • Can you provide an example of the input string? – Vincent F Oct 26 '15 at 16:50
  • Never mind, I have an answer – Vincent F Oct 26 '15 at 16:58
  • For anyone else who might be interested, an example of an input string is "BATT:xx%" where xx could be a single, two, or three-digit number. Now, I do recognize that this particular function is simple enough to write some validation logic for without the need of error catching, but I'm mainly interested in knowing what to do in the case where you can't easily validate the input and need to catch errors. – Jason O Oct 26 '15 at 20:50

1 Answers1

1

So the problem String startIndex and characters functions do not throw and exception that can be caught by the swift do try catch block. See The Swift Programming Language (Swift 2.1) - Error Handling documentation for more info.

So I rewrote the code to deal with parsing of the integer without crashing

func parseBatteeryLevel(inputStr : String) -> Int {
    if inputStr.hasPrefix("BATT") && inputStr.containsString("%") {
        let start = inputStr.startIndex.advancedBy(5)
        let indexOfPercent = inputStr.characters.indexOf("%")

        if (indexOfPercent != nil) {
            let end = indexOfPercent!.advancedBy(-1)
            let batteryLevel = inputStr.substringWithRange(start...end)

            if let level = Int(batteryLevel) {
                return level
            }
        }

        return 0

    } else {
        print("Return Value Parse Error: \"\(inputStr)\"")
        return 0
    }
}
Ky -
  • 30,724
  • 51
  • 192
  • 308
Vincent F
  • 371
  • 3
  • 17
  • Hi Vincent, Thank you for the proposed solution. However, this begs a more fundamental question: How do you handle errors, in Swift, for functions that don't throw any errors?? Thankfully, this one has a workaround, but what do you do in the case where you can't completely validate the input? – Jason O Oct 26 '15 at 20:47
  • 1
    its a good question, I really believe Apple is still pondering how to do error handling as a whole. According to their docs it really should be handled using the do/try blocks but in the case of advancedBy, et el we are left with simple validation for the moment – Vincent F Oct 26 '15 at 21:02
  • 1
    some more info about this topic here http://stackoverflow.com/questions/24010569/error-handling-in-swift-language – Vincent F Oct 26 '15 at 21:04