3

is there any way to catch it? Or is this a bug?

Cœur
  • 37,241
  • 25
  • 195
  • 267
David
  • 4,235
  • 12
  • 44
  • 52
  • It's not a bug, it's a programming error. Don't pass invalid arguments to the method and you won't get the error. It's letting you know that you're doing something very wrong. – Jason Coco Mar 02 '11 at 04:11
  • 1
    Hmm okay - forget the added question "or is this a bug". I just want to know how to catch this exception NSInvalidArgumentException. – David Mar 03 '11 at 17:42
  • 1
    it is a bug http://stackoverflow.com/questions/6412263/nsinvalidargumentexception-not-being-caught-in-code – Felipe Sabino Aug 17 '11 at 00:22

4 Answers4

7

So to answer this question, I used the following:

@try{ 
   //your code
} @catch (NSException* exception) {
   NSLog(@"Got exception: %@    Reason: %@", exception.name, exception.reason);
}

and the string NSInvalidArgumentException is printed for 'exception.name' so clearly one could just test that exception.name for the actual exception type.

Not the prettiest, but it works.

brush51
  • 5,691
  • 6
  • 39
  • 73
David
  • 5,991
  • 5
  • 33
  • 39
5

If I understand you correctly, you ask why you can't catch the NSInvalidArgumentsException. To be precise, the exception is not caught even if you try to catch it as NSException, which should always work. I also experienced this problem and after looking around - this issue indeed looks like an Apple's bug. Please see this page. People report there that the issue exists only on simulators and works correctly on real devices.

Moshe Kravchik
  • 2,341
  • 2
  • 16
  • 18
0

As @David mentioned we can use below code

@try{ 
   //your code
} @catch (NSException* exception) {
   NSLog(@"Got exception: %@    Reason: %@", exception.name, exception.reason);
}

and @Moshe Kravchik mentioned, there situations were some exceptions are not caught , that is mainly when we dispatches new block in a queue , so I would recommend to add separate try catch block for each queue dispatches.

ie, try..catch in main() will not catch the exception happened in AppDelegate class, so need to add separate try..catch in AppDelegate

eg:

- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
    @try{

        self.viewController = [[MainViewController alloc] init];

        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            @try{
                NSLog(@"This is a block");
                NSObject * b= nil;
                [NSArray arrayWithObject:b];
            } @catch (NSException* exception) {
                NSLog(@"Got exception: %@    Reason: %@", exception.name, exception.reason);
            }
        });

        return [super application:application didFinishLaunchingWithOptions:launchOptions];
    } @catch (NSException* exception) {
        NSLog(@"Got exception: %@    Reason: %@", exception.name, exception.reason);
    }
}

for any uncaught exception, we should use NSSetUncaughtExceptionHandler, that will not stop application from crashing.

void onUncaughtException(NSException* exception)
{
    NSLog(@"onUncaughtException : %@", exception.reason);
}

int main(int argc, char* argv[])
{
    @autoreleasepool {
        NSSetUncaughtExceptionHandler(&onUncaughtException);
        int retVal = UIApplicationMain(argc, argv, nil, @"AppDelegate");
         return retVal;
    }
}

for signals other than exception , like bad memory usages etc we should listen for particular signal

void signalHandler(int signal)
{
    NSLog(@"Got signal %d",signal);
}

    signal(SIGPIPE, &signalHandler);
    signal(SIGABRT, &signalHandler );
    signal(SIGHUP, &signalHandler );
    signal(SIGINT, &signalHandler );
    signal(SIGQUIT, &signalHandler );
    signal(SIGILL, &signalHandler );
    signal(SIGIOT, &signalHandler );
    signal(SIGFPE, &signalHandler );
    signal(SIGSEGV, &signalHandler );
    signal(SIGSYS, &signalHandler );
    signal(SIGPIPE, &signalHandler );

More details about uncaught exception here.

Shihab
  • 111
  • 4
  • Regarding my statement "that will not stop application from crashing.", it is applicable only while debugging, ,while actual run there is mechanism to continue as mentioned in the referred link of cocoawithlove.com shown in my post. – Shihab Jan 15 '19 at 15:23
-5

It is a bug. Specifically, a bug in your code. NSInvalidArgumentException means you've passed bad data into a method. Frequently this means you've passed nil as an argument that doesn't allow nil. The exception description should provide more information as to what method/argument is bad.

Lily Ballard
  • 182,031
  • 33
  • 381
  • 347
  • 2
    I just want to be able to catch that exception. i know what it means. – David Mar 03 '11 at 17:43
  • This isn't the sort of exception you catch. This is the sort of exception you make sure is never thrown to begin with. – Lily Ballard Mar 03 '11 at 18:11
  • Hmm you got me thinking differently then. Well if anyone knows how to catch this then let us know, otherwise this is something you can't catch in the first place, but just prevent like what Kevin mentioned. – David Mar 04 '11 at 09:22
  • If you are doing any automatic KVC, you can get this exception if everything is not perfect. To make things worse, you can't get the argument type to prevent sending the wrong object to a setter. It would be nice to catch it and the fact that it doesn't work when catching NSException is a bug. – Peter DeWeese Jun 09 '11 at 06:00
  • 2
    I think this is wrong. For example, the launch method of NSTask generates a NSInvalidArgumentException if a process cannot be created. One of the reasons a process cannot be created is if it doesn't exist or can't be found. That is not necessarily a programming error. In particular, NOT catching this exception would be a programming error. – David Oct 04 '12 at 13:02
  • 1
    @David: "for example"? I think that's the only instance anywhere of `NSInvalidArgumentException` being used for a runtime error condition, and something that I consider a bad bug in NSTask that, unfortunately, can never be fixed. – Lily Ballard Oct 04 '12 at 18:59
  • Yes, you're right in theory. But it's a good example of Yogi Berra's famous quote "In theory there is no difference between theory and practice. In practice there is". I agree that the exception name is wrong for the situation I encounted. Nevertheless, this was the first time I encountered this particular exception and I still needed to deal with it. Finding no answer, it seemed worthwhile to comment on it as well as provide a solution. – David Oct 05 '12 at 11:13
  • 2
    I'm in the same spot as @PeterDeWeese This exception can be thrown by `NSKeyedUnarchiver` when the archive exists on disk but is not in perfect condition (i.e. you made an upgrade, the file was corrupt from previous version of your app etc.) All I/O code always have a chance to error out. You must have a way to deal with those error condition. And if it is impossible to catch, then we are simply doomed. – chakrit Jul 01 '14 at 19:36
  • @chakrit Well you certainly *can* catch it. What makes you think it's impossible to catch? A simple `@try { foo() } @catch (NSException *e) { bar(e) }` catches the exception just fine. – Lily Ballard Jul 02 '14 at 07:18
  • @KikoLobo It absolutely is. There is no valid reason to ever try to catch `NSInvalidArgumentException`. Doing so means you're knowingly passing invalid data into a method and you're just hoping that the program is still in a usable state after you try and catch the resulting exception. If the method you called directly throws the exception, it probably is, but if the exception comes from a nested method call then all bets are off because the method you called may have started doing something that leaves the program in a bad state if it's interrupted by an exception. – Lily Ballard Mar 17 '16 at 17:06