views:

610

answers:

2

I am developinga Core Data app for the iPhone, and I am new to the whole platform etc.

My question is, how much should I look for and handle errors and exceptions, for example when opening up the persistent store. Looking at the "Locations" Core Data Tutorial for example (hope its OK to quote it here like this):

(Se comments in the code for some of my conserns)

- (void)applicationDidFinishLaunching:(UIApplication *)application {
   ...    
   NSManagedObjectContext *context = [self managedObjectContext];
   if (!context) {
       // Handle the error. Can this ever happen with this code? (see next comment below)



- (NSManagedObjectContext *) managedObjectContext {
   ...
   NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
   // it seems even if I get an error or exception down in persistentStoreCoordinator,
   // coordinator will still never be nil, or?  
   if (coordinator != nil) {
        managedObjectContext = [[NSManagedObjectContext alloc] init];
        [managedObjectContext setPersistentStoreCoordinator: coordinator];
   }
   return managedObjectContext;   
}



- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
   ...
   NSError *error;
   // should i have an:  if managedObjectModel != nil   here?
   persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] [initWithManagedObjectModel: [self managedObjectModel]];
   //need a @try here too?
   if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:nil error:&error]) {
       // Handle error, do what?   
   }    
   return persistentStoreCoordinator;    
}


- (NSManagedObjectModel *)managedObjectModel {
   ...
   //should have a @try here? But how to handle caught exceptions? Just return nil?
   managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];    
   return managedObjectModel;
}

So the question is really where to look for errors, where to look for exceptions, how and when to propagate them upwards, and how to handle severe errors on the iPhone in a good way?


Edit: after receiving some answers to this and my other related question I have some clearifications of what I try to ask:

I now understand exceptions in cocoa are mostly for finding programmer errors, not runtime errors. Would you go as far as not including any exception handling when shipping the app (if not added for debug reasons)? Or should I still program defensively and use a lot of @try anyway?

As the iPhone apps are sandboxed and the user cant get to the file system, what possible runtime errors are smart to look for when designing a sqlite based core data app? I mean, the database file is not likely to disapear....but perhaps a future upgrade could fail leaving an old invalid sqlite database....what is good practise?

Also, other things like object alloc are probaly extremely unlikely to fail? You would get a low memory warning long before that happens....or...?

And, what is good programming practise considering error and exception handling in the above example, where I can get an error "deep down" in the methods...should I handle the error down there or wait until it reaches the top in some form (a nil object for example), or handle them all in a chain reaction?

And, how to handle them? Log to NSLog and go on? Show a modal info box and lock up waiting for the user to exit the app? Or "Error xxx, press OK to exit app"?

And, is there any way to show a modal dialog directly? I noticed that some errors I provoked that would display a dialog never showed that because the app continued and later crashed....is there a SHOW NOW method?

Lots of questions, hope you would be interested to answer at least some of them, and that this could be of interest to others!

Rgds PM

+2  A: 

As I said in a comment on your other question, exceptions are only used by the Cocoa API to indicate things that it looks like the programmer has got wrong - an array is out of bounds, a Core Data database has the wrong schema etc. Errors are used to indicate things which the user could cause to happen - a file doesn't exist, a network operation didn't complete etc. So as a rough rule of thumb, look for exceptions during development and crush them as programmer-introduced bugs. Be prepared to handle and recover from errors in production.

The one important edge case on the Mac is Distributed Objects, which uses exceptions for things like the other end of the connection going away or the security validation not succeeding.

Graham Lee
Thank you for an even better explanation of this! I have edited the post now to further explain what else I was trying to understand.
Petter Magnusson
+1  A: 

You should check for errors if the documentation says to do so.

For example, in the documentation for the NSPersistentStoreCoordinator:addPersistentStoreWithType:configuration:URL:options:error: documentation, notice that it says:

Return Value

The newly-created store or, if an error occurs, nil.

That means an nil is returned in the case of an error. You should check for it, because otherwise you will have a reference to nil, which will cause a runtime exception once you try to use it. That is not a graceful way for an application to operate - crashing unexpectedly is just not an acceptable behavior for user applications of any sort.

In Objective-C you generally should not have to deal with exceptions because they are used for exceptional situations. Some other languages use exceptions as a better way of indicating normal error conditions for a variety of very good reasons. That, however, is not the convention in Objective-C.

So the answer to your question is: you should always handle errors when the API tells you the function can return a nil in the case of error condition.

If the documentation tells you to expect and handle exceptions, then do so. Otherwise do not. The only exception to this is iff you know what you are doing and why.

groundhog
Thank you, will check the documentation for all important calls! I could still use some further help on programming practise as mentioned above in my edited question....
Petter Magnusson