Tutorial :how do I catch a NSRangeException?



Question:

I want my app to continue gracefully when the online server messes up. I tried to wrap the dangerous line in a @try block. Yet it is still crashing like so:

the method:

+ (NSArray *)findAllFor:(NSObject *)ratable {        NSString *ratingsPath = [NSString stringWithFormat:@"%@%@/%@/%@%@",       [self getRemoteSite],       [ratable getRemoteCollectionName],       [ratable getRemoteId],       [self getRemoteCollectionName],       [self getRemoteProtocolExtension]];         Response *res = [ORConnection get:ratingsPath withUser:[[self class] getRemoteUser]        andPassword:[[self class] getRemotePassword]];       NSArray *ratings;       @try {            ratings = [self fromXMLData:res.body];       }       @catch (NSException *e) {            ratings = [NSArray array];       }      return ratings;  }  

the stack trace:

  Program received signal:  “SIGABRT”.  2010-08-07 16:38:51.846 TalkToHer[68608:7003] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSArray objectAtIndex:]: index 1 beyond bounds [0 .. 0]'  *** Call stack at first throw:    (   0   CoreFoundation                      0x02932919 __exceptionPreprocess + 185     1   libobjc.A.dylib                     0x02a805de objc_exception_throw + 47     2   CoreFoundation                      0x0292858c -[__NSArrayI objectAtIndex:] + 236     3   TalkToHer                           0x00009fa7 -[FromXMLElementDelegate parser:didEndElement:namespaceURI:qualifiedName:] + 425     4   Foundation                          0x0017bcc1 _endElementNs + 453     5   libxml2.2.dylib                     0x02d9deb6 xmlParseXMLDecl + 1353     6   libxml2.2.dylib                     0x02da8bc1 xmlParseChunk + 3985     7   Foundation                          0x0017b4c2 -[NSXMLParser parse] + 321     8   TalkToHer                           0x0000b14d +[NSObject(XMLSerializableSupport) fromXMLData:] + 201     9   TalkToHer                           0x00031a6c +[Rating findAllFor:] + 320     10  TalkToHer                           0x00032d67 -[FirstClassContentPiece(Ratable) updateRatings] + 96     11  TalkToHer                           0x00004d5f __-[InspirationController tableView:didSelectRowAtIndexPath:]_block_invoke_3 + 33     12  libSystem.B.dylib                   0x9792efe4 _dispatch_call_block_and_release + 16     13  libSystem.B.dylib                   0x97921a4c _dispatch_queue_drain + 249     14  libSystem.B.dylib                   0x979214a8 _dispatch_queue_invoke + 50     15  libSystem.B.dylib                   0x979212be _dispatch_worker_thread2 + 240     16  libSystem.B.dylib                   0x97920d41 _pthread_wqthread + 390     17  libSystem.B.dylib                   0x97920b86 start_wqthread + 30    )  terminate called after throwing an instance of 'NSException'  

Is my syntax for @try @catch wrong? I attempted to add a @catch block for NSRangeException but it seems that's not the right approach (it's not a class).

Also, the server error is caused by [ratable getRemoteId] sometimes returning (null) instead of an integer. This behavior seems pretty unpredictable; if anyone has a clue why ObjectiveResource might be doing that it would be helpful. But I still would like to know how to use @try @catch.


Solution:1

You don't. You fix your code to not throw an exception under these circumstances.


Solution:2

As I now understand it, throwing exceptions should only be done to alert users of your library that they have made a programming error. I am still curious why the syntax I used did not prevent the crash. I know the error was occurring several levels down; but the @try {} @catch {} block should handle all methods called by the methods I call...

At any rate, here is the fixed code, for anyone who wants to fetch scoped objects from a Rails-style restful resource.

+ (NSArray *)findAllFor:(NSObject *)ratable {      NSString *ratingsPath = [NSString stringWithFormat:@"%@%@/%@/%@%@",                            [self getRemoteSite],                            [ratable getRemoteCollectionName],                            [ratable getRemoteId],                            [self getRemoteCollectionName],                            [self getRemoteProtocolExtension]];        Response *res = [ORConnection get:ratingsPath withUser:[[self class] getRemoteUser]                         andPassword:[[self class] getRemotePassword]];      NSError **aError;      if([res isError]) {          *aError = res.error;          return nil;      }      else {          return [self performSelector:[self getRemoteParseDataMethod] withObject:res.body];      }  }  

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »