8

I'm used to working with SQL database, I'm new to Realm and, so far, I'm really impressed by the ease of use of this new mobile database. But there is something that I really don't undestand: how to handle error throwing?

Take this simple example:

I want to store in a Realm DB some market stocks.
Each stock has a "symbol" as a unique identifier: APPL for Apple Inc, TSLA for Tesla Motors Inc, etc.
I believe it would make sense to declare these symbols as primary keys, since it's not possible to have multiple times the same symbol in the database
When user clicks on a symbol (among a list of symbols), this symbol is saved in db.

In this Raywenderlich tutorial, it is said: "To simplify the code required in this tutorial, you’ll be used try! when calling Realm methods that throw an error. In your own code, you should really be using try and do / catch to catch errors and handle them appropriately."

So according to the following pattern:

do {
    try realm.write {
        realm.add(symbol)
    }
}
catch let error as NSError {
    print("Something went wrong: \(error.localizedDescription)")
}

So far it makes sense.
And if a user clicks on a symbol that is already in the database, I get (very logically) an error:

*** Terminating app due to uncaught exception 'RLMException', reason: 'Can't set primary key property 'symbol' to existing value 'APPL'.'

The problem is that this error is not catched during run time: I've got a crash instead.

My question is not about how to avoid such a crash, I understand of course that it's easy to avoid it by doing a simple testing before writing anything in the database :)

My question is how do we do in Realm to catch potential writing errors?
Am I doing something wrong?

SebT
  • 135
  • 2
  • 6

3 Answers3

11

do/try/catch in Swift catch Swift Errors, which are an entirely distinct thing from Objective-C exceptions. Realm follows Foundation's pattern for error reporting: API misuse errors throw exceptions which are not intended to be caught (and can't be caught in Swift), and recoverable errors throw Swift errors (or use NSError out parameters in Objective-C).

Adding an object with a duplicate primary key is considered API misuse, so it's a fatal error as the route for "handling" it is to fix the bug in your code. An example of a recoverable error which would produce a Swift error that would be caught by catch is running out of disk space while trying to save the new data.

Thomas Goyne
  • 8,010
  • 32
  • 30
  • 1
    Ok thanks for the very precise answer. It seems weird to me not to be able to catch errors in order to handle them, but I do understand the philosophy behind it. I assume finally that, contrary to what is said in the Raywenderlich tutorial, there's not much interest with Realm to verbose the code with "do/try/catch" syntax. Should stick to the simple "try!" syntax... (except maybe for the out of disk space type of error) – SebT Jun 28 '16 at 15:51
  • 2
    Thanks for the good answer. In my opinion this is very poor from realms perspective – George Bafaloukas May 26 '17 at 10:40
4

There are two distinct types of error: programmer error, and expected errors. Realm handles these two types of errors differently.

Programmer error covers cases such as accessing objects from incorrect threads, out-of-bounds collection access, attempting to insert an object with a duplicate primary key, and so forth. Realm responds to these programmer errors by throwing an Objective-C exception. These exceptions are not intended to be caught and handled as they're indicative of a bug in a Realm user's code.

Expected errors cover things like files not existing, permission errors, failures to write to disk. These are things that can happen even with correctly-written code due to factors outside of the programs control. These are exposed as NSErrors and can be caught from Swift using do / try / catch. Note that Realm's Objective-C API has some convenience methods that don't expose the NSError. In these cases an expected error will throw an exception as there's no other avenue for Realm to communicate the failure. Rather than attempting to catch and handle exceptions raised by these convenience methods, you should use the variant of the API that returns an NSError instead.

bdash
  • 18,110
  • 1
  • 59
  • 91
  • 1
    Thanks @bdash for the complement of information. I don't have enough "reputation" to do +1, but I would have done if I could... – SebT Jun 28 '16 at 17:47
0

Hi, the error line said "to existing value", don't you try to write more than one time the same primary key with 'APPL' ? you need to update it, not override.

if you try to "add" again the same value, it's gonna stop you.

(sorry for bad english x) )

Oleg G.
  • 550
  • 5
  • 25
  • Thanks for your answer. You totally agree: the error is due to the fact that I'm trying to add an object that is already in db (with same primary key). The cause of the error is clear for me, but what I don't understand is how I catch the error during run time instead of having a crash? – SebT Jun 28 '16 at 10:49
  • if this things can help you ? https://realm.io/docs/swift/latest/#creating-and-updating-objects-with-primary-keys – Oleg G. Jun 28 '16 at 10:56
  • It surely helps in this particular case, but that was only an example. My question is more general and is about catching error during writing operation: how do we do it? – SebT Jun 28 '16 at 10:58
  • really on during, i don't think it's a good idea, because you don't gonna drive a car and kill all people on the road and see the result after. You need to check before if people was in front of you. I think that's the same thinks right here. make this -> var tanDogs = realm.objects(Dog.self).filter("yourKey = 'whatYouExpect'") and look for result, if it's nil, you show a message error and everything ok i guess keep me posted – Oleg G. Jun 28 '16 at 11:03
  • Thanks Oleg. We agree on what has to be done to avoid such a crash (as evoked by anticipation in my question: just doing a simple testing before writing anything in the database). But the question is about "catching errors", as recommended in the Raywenderlich tutorial. Does it mean that there's no way to catch error in Realm? But in this case, why Raywenderlich recommends it? – SebT Jun 28 '16 at 11:10
  • in this issue: https://github.com/realm/realm-cocoa/issues/2657 , they are talking about deleting realm file etc. but the realm member said it's better to kill app .. it's strange effectively :/ you have the same problem right here : http://stackoverflow.com/questions/2132759/php-catch-exception-and-continue-execution-is-it-possible. keep me posted – Oleg G. Jun 28 '16 at 12:29