Best Practice - NSError domains and codes for your own project/app

33,918

Solution 1

I personally use a reverse-DNS style domain. For example:

NSError * myInternalError = [NSError errorWithDomain:@"com.davedelong.myproject" code:42 userInfo:someUserInfo];

The third part of the domain (@"myproject") is just used to differentiate the errors from this project ("My Project") from errors in another project ("My Other Project" => com.davedelong.myotherproject).

It's a simple way to ensure that I'm not going to conflict with anyone else's error domains (if I'm using 3rd party code), unless that developer is purposefully trying to mess with just me (which I believe would be highly unlikely...).

As for code numbering conflicts, don't worry about that. Just as long as codes are unique within a domain, you should be OK.

As for translating errors, that's up to you. Whatever you do, make sure you document it well. Personally, I usually just pass on framework-generated errors as they came to me, since I'm never quite sure that I'll handle all the codes and translate all of the userInfo into something more specific to my project. The frameworks could change and add more codes, or change the meaning of existing codes, etc. It also helps me more specifically identify where the error came from. For example, if my StackKit framework generates an error in the com.stackkit domain, I know that it's a framework problem. However, if it generates an error in the NSURLErrorDomain, then I know that it specifically came from the URL loading mechanism.

What you could do is capture the framework generated error and wrap it in a new error object that has your domain and a generic code, something like kFrameworkErrorCodeUnknown or something, and then place the captured error in the userInfo under the NSUnderlyingErrorKey. CoreData does this a lot (for example, if you try to save: an NSManagedObjectContext, but you have relationship integrity errors, you'll get a single error back, but the NSUnderlyingErrorKey will contain much more information, like specifically which relationships are wrong, etc).

Solution 2

I don't have enough rep to comment, but for the accepted answer by Dave DeLong, it might be slightly better to use [[NSBundle mainBundle] bundleIdentifier] instead of @"com.myName.myProject". This way, if you change your name or project's name, it will be reflected accurately.

Solution 3

How to create a custom NSError:

First create a Dictionary of the error message

NSDictionary *userInfo = @{   
   NSLocalizedDescriptionKey: NSLocalizedString(@"Unknown Error - Please try again", nil),
   NSLocalizedFailureReasonErrorKey: NSLocalizedString(@"Unknown Error - Please try again", nil),
   NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString(@"Unknown Error - Please try again", nil)
                                               };
NSError *error = [NSError errorWithDomain:[[NSBundle mainBundle] bundleIdentifier] 
  code:-58 userInfo:userInfo];

Then assign the userInfo to the NSDictionary and your done.

Share:
33,918

Related videos on Youtube

Neal L
Author by

Neal L

Updated on July 08, 2022

Comments

  • Neal L
    Neal L almost 2 years

    There is a previous SO post regarding setting up error domains for your own frameworks, but what is the best practice regarding setting up error domains and custom error codes for your own project/app?

    For example, supposing you're working on a Core Data-intensive app with lots of validations, should you just stick with the "off the shelf" Core Data error codes (such as NSManagedObjectValidationError from CoreDataErrors.h) or should you create your own MyAppErrors.h and define errors with more specificity (i.e., MyAppValidationErrorInvalidCombinationOfLimbs?

    Creating a custom error domain and set of error codes could significantly disambiguate your code, but is it too much overhead to maintain and does one have to worry about error code numbering conflicts? Or are there other concerns here?

  • Johan Karlsson
    Johan Karlsson over 9 years
    Since apple also uses reverse DNS it seems appropriate for other to use this style as well.
  • Juul
    Juul over 9 years
    Good idea. If you're using Swift, you should use the unwrapped optional: NSBundle.mainBundle().bundleIdentifier! (if you know the bundle identifier is set, which I guess will be most likely)
  • zrslv
    zrslv about 9 years
    Why would you want to reflect project name changes in the error domain?
  • Connor
    Connor about 9 years
    @zrxq There is value in having different error domains for sure, but imagine you misspelled your project or you changed your name an wanted it reflected everywhere. Better have it dynamically set than hard coded.
  • zrslv
    zrslv about 9 years
    @vare That much is clear, I don't really understand what practical benefits would that provide. My understanding is those identifiers just need to be unique in the context of the app, that's all. Okay, maybe you just want them to be more aesthetically pleasing, I get it!
  • Connor
    Connor about 9 years
    Yeah, you bring up a good point. There are times when you want the domain to be unique, I would assume ... for example perhaps if you're create an SDK or (cocoa)Pod, you would want your error domain to reflect where it came from, not the project's name. EDIT: I also (in my answer) wanted to point out that @"com.myName.myProject" is identical to the bundleIdentifier in this case, which people might not know.