how to print error in catch - swift

catch let error as LocksmithError{
print(error)// it would print the case of the error.
}
However if I do
catch LocksmithError.Duplicate{
}
catch{
print (LocksmithError) // Obviously I would just print LocksmithError, it won't print the case
print (LocksmithError.rawValue) // prints nothing
}
My question is: Using the 2nd approach is there any that I can actually retrieve and the value/case of the error? Or if I don't get the value right at the entry point ie the catch, then I miss the chance of doing it!

The catch blocks are exclusive cases, evaluated in order. When a match succeeds, we stop.
So, let's just think about this structure:
catch LocksmithError.Duplicate {
// 1
print("duplicate")
}
catch {
// 2
print(error)
}
If we are at 1, then what is in scope is the LocksmithError.Duplicate.
If we are at 2, then what is in scope is every other kind of error that gets caught. There's no way you can get hold of the LocksmithError.Duplicate here, because ex hypothesi it would have been caught in 1 and we wouldn't be here.
Now, the way I would do it is like this:
catch let err as LocksmithError {
// 1
print(err)
}
catch {
// 2
print(error)
}
That may be the sort of thing you are after; it gives us a value err that carries the error into the curly braces in 1. (The automatic error value exists only the final catch-all catch block.)

Related

If I put a try statement in a for loop, where does the catch go using swift 5.1

I am trying to see if an SQLite.swift database is setup by selecting the last row, and if it's not setup, I will reload the database table from a file.
But I'm using code based on the SQLite.swift documentation, which doesn't provide enough context in the far too brief example code.
let query = Bible.select(id, Book, Chapter, Verse, KJV)
.filter(id == 31102)
for verse in try! db.prepare(query) {
print("The Bible is in the DB.\n")
DataLoaded = true
} catch {
DataLoaded = false
}
I understand the '!' after try suppresses the error, so the catch I've put at the end is doing nothing, but if I remove the '!' an error message says "Errors from here are not handled".
If I take away the '!', where should I put the catch?
The for loop is irrelevant. The catch needs to be paired with a do.
do {
// anything involving a try
} catch {
}
So your code should be more like this:
do {
for verse in try db.prepare(query) {
print("The Bible is in the DB.\n")
}
DataLoaded = true // Put this inside the loop if loading any data, and not all, is considered success
} catch {
DataLoaded = false
}
And don't use try! with catch. Just use try.

How to handler an error of MKDirectionsRequest

I'm not very familiar with error handling and so any advice would be really appreciated.
My code makes multiple calls recursively to the Apple API for calculating a route as it needs to calculate the distance for multiple options.
do {
directions.calculate(completionHandler: {(response, error) in
let response = (response?.routes)! //This line bugs out
for route in response {
//code
completion(result, error)
}
})
}
catch {
print(error.localizedDescription)
}
It tends to crash on the 5th or 6th time, and I wondered if there was a way to stop the application crashing and notify instead.
Thanks
There's no point in using a do-catch block, since there's no throwable function in your code, so you won't be able to catch any errors. In Swift you can only catch errors thrown by a function marked throws, all other errors are unrecoverable.
You should safely unwrap the optional response, since it might be nil, in which case the force unwrapping would cause an unrecoverable runtime error that you have already been experiencing.
You can use a guard statement and optional binding to safely unwrap the optional response and exit early in case there's no response.
directions.calculate(completionHandler: {(response, error) in
guard let response = response, error == nil else {
completion(nil,error)
return
}
for route in response.routes {
....
completion(result, nil)
}
})

try catch like Java in swift

I'm trying to achieve something like this:
try {
num1 = 0;
num2 = 62 / num1;
num3 = num3/2;
}
catch (ArithmeticException e) {
/* This block will only execute if any Arithmetic exception
* occurs in try block
*/
}
But in Swift I have to use:
do {
let sandwich = try makeMeSandwich(kitchen)
let sandwich2 = try makeMeSandwich(kitchen2)
try abc(kitchen2) // no return type
print("i eat it \(sandwich)")
} catch {
print("Not me error")
}
I have to specify try for every check. Is there something I can do just like in Java for the whole method?
If no return type method like
try abc(kitchen2)
it shows me the below warning:
No calls to throwing functions occur within 'try' expression
and in a catch block:
'catch' block is unreachable because no errors are thrown in 'do' block

Swift: if a do return try fails does catch execute

I am working on a piece of code that is going to fetch an array of NSManagedObjects from CoreData. When using a do catch statement in my code it doesn't seem right to do it this way, but it is the simplest way I can write this line of code.
In any other scenario when you use the return statement you are jumping out of the current function you are in. And you can be assured that no other code in your function will execute past the return statement. I am wondering if the same applies to Swift's do catch paradigm.
class func getAll() -> [MMNotification] {
let context = appDelegate.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<MMNotification>(entityName: "MMNotification")
do {
return try context.fetch(fetchRequest)
}
catch {
// Will this 'catch' if the try fails,
// even if we said we are 'return'ing right before the 'try'?
return []
}
}
Here I am fetching a list of notifications stored in CoreData. In the do block you can see the line of code in question.
QUESTION
Will the catch block execute if the try fails after already stating that the function should return?
What you have should work as expected. Basically what happens is if a throw occurs at any time within a do, the catch is called and any code after the throw will not be executed.
Yes, the catch block will execute if the try in return try fails. The return will not happen.
Here's a little code to prove it to yourself. Paste it into a new playground to try it out.
import UIKit
let shouldFail = true
enum DemoError:Error {
case shouldFail
}
func failableGetter() throws -> String {
if shouldFail { throw DemoError.shouldFail }
return "Succeeded"
}
func fetchInfo() -> String {
do {
return try failableGetter()
} catch {
return "Failed"
}
}
print(fetchInfo()) // "Failed" or "Succeeded" depending on shouldFail
When shouldFail is true, the failableGetter() throws an error and the do-catch in fetchInfo() skips to the catch section before returning.
When shouldFail is false, the failableGetter() doesn't fail and fetchInfo() returns the result.
Adding to this answer. Scope matters a bit here. Code inside the do block code after a throw will NOT be executed. However, code further down outside of the scope of the do block will be executed. I made a simple playground you can run to see for yourself.
import Foundation
let error = NSError(domain: "", code: 123, userInfo: [NSLocalizedDescriptionKey: "My error"])
func functionThatAlwaysThrows() throws {
throw(error)
}
func myFunction() {
do {
try functionThatAlwaysThrows()
// This will never print
print("Continuing after throw inside do scope")
} catch let err {
print("Caught Error: \(err.localizedDescription)")
}
// This will always print
print("Continuing after throw outside do scope")
}
Output:
Caught Error: My error
Continuing after throw outside do scope
If you want more information on Error handling you can take a look at the docs

CNContactStore Save Error

CNContactStore's executeSaveRequest(_:) method throws an error according to the documentation.
I am trying to catch this error in a do/catch, but I cannot figure out what error I need to catch.
do{
try store.executeSaveRequest(saveRequest)
} catch *???* {
//alert the user
}
What is supposed to replace the ???'s in the code above?
You have a few options actually.
Catch any error without knowing the error
catch {...}
Catch any error with the specific error message
catch let error { // Use error }
Use exhaustive catch clauses to handle specific errors using the CNErrorCode enum.
enum CNErrorCode : Int {
case CommunicationError
case DataAccessError
case AuthorizationDenied
case RecordDoesNotExist
case InsertedRecordAlreadyExists
case ContainmentCycle
case ContainmentScope
case ParentRecordDoesNotExist
case ValidationMultipleErrors
case ValidationTypeMismatch
case ValidationConfigurationError
case PredicateInvalid
case PolicyViolation
}