4

I'm running fuzz testing on an application, and so am looking specifically for runtime errors that aren't handled. The application is written in both ObjC and Swift, but the unit tests are written in Swift.

I understand the basis of swift isn't to catch arbitrary runtime exceptions, but this is purely for unit tests. How do I catch runtime these exceptions (i.e. index out of bounds etc.)

Jacob Parker
  • 287
  • 3
  • 13
  • Are we talking about Obj-C exceptions or Swift exceptions? Swift exceptions are not easy to handle. Obj-C exceptions can be caught simply using an utility Obj-C function. – Sulthan Mar 23 '17 at 15:19
  • I think most of the errors will come from ObjC—a solution for just those would suffice! – Jacob Parker Mar 23 '17 at 15:22
  • 1
    Possible duplicate of [Catching NSException in Swift](https://stackoverflow.com/questions/32758811/catching-nsexception-in-swift) – kelin Apr 07 '19 at 14:22

1 Answers1

7

To catch Obj-C exceptions in Swift, I am using a simple Obj-C class:

#import "ObjC2Swift.h"

@implementation ObjC

+ (id)catchException:(id(^)())tryBlock error:(__autoreleasing NSError **)error {
    @try {
        id result = tryBlock();
        return result;
    }
    @catch (NSException *exception) {
        if (error) {
            *error = [[NSError alloc] initWithDomain:exception.name code:0 userInfo:exception.userInfo];
        }
        return nil;
    }
}

@end

In Swift called as

let result = try? ObjC.catchException { ... dangerous code here ... }

You might need a different variant for blocks that don't return anything.

Not to be abused. Obj-C exception are evil and I am using this only because I need a library that uses them.

Sulthan
  • 118,286
  • 20
  • 194
  • 245
  • Great idea, upvoted. I made a couple of minor enhancements: 1) Return the exception to Swift as the return value of catchException(), so that it can check the exception class, or any properties like reason, including custom properties in an NSException subclass. Don't convert it to an NSError. 2) Catch id, in case someone throws an exception that doesn't derive from NSException. – Kartick Vaddadi Sep 17 '17 at 06:53
  • @VaddadiKartick If you want to use Swift `try` you should not return the exception and you need the `NSError` conversion :) The `NSError` handling in Obj-C, on which Swift `try` is based supposes that you return `nil` (or `false`) if there is some error. – Sulthan Sep 17 '17 at 07:50
  • I understood your preference. I was just trying to say that I don't mind getting the exception as a return value, and that I want all the information available in Objective-C to be passed back to Swift. – Kartick Vaddadi Sep 17 '17 at 10:21
  • I tried your solution but I get 'Type "ObjC' has no member 'catchException" I used the header-bridge-file to add objC Implementation there, is this wrong? any Idea what I am doing wrong? Thanks – Iman Feb 11 '19 at 21:34
  • @Zich You need a header file with the method declaration and the implementation file above. Then you import the header file from the bridging header. – Sulthan Feb 11 '19 at 21:39
  • @Sulthan OK, Thanks for your fast reply. – Iman Feb 11 '19 at 21:42