Calling Nsexception.Raise() in Swift

Calling NSException.raise() in Swift

The problem seems to have been that I didn't treat the error as an optional. The following works:

var error: NSError?
NSException.raise("Exception", format:"Error: %@", arguments:getVaList([error!]))

Or you could do the following in case error is nil:

NSException.raise("Exception", format:"Error: %@", arguments:getVaList([error ?? "nil"]))

Manually throw exception instead of returning value in Swift

I needed fatalError("")

func head<T>(xs: [T]) -> T {
if (xs.count > 0) {
return xs.first!
} else {
fatalError("list is empty")
}
}

this code works just fine.

Catching NSException in Swift

Here is some code, that converts NSExceptions to Swift 2 errors.

Now you can use

do {
try ObjC.catchException {

/* calls that might throw an NSException */
}
}
catch {
print("An error ocurred: \(error)")
}

ObjC.h:

#import <Foundation/Foundation.h>

@interface ObjC : NSObject

+ (BOOL)catchException:(void(^)(void))tryBlock error:(__autoreleasing NSError **)error;

@end

ObjC.m

#import "ObjC.h"

@implementation ObjC

+ (BOOL)catchException:(void(^)(void))tryBlock error:(__autoreleasing NSError **)error {
@try {
tryBlock();
return YES;
}
@catch (NSException *exception) {
*error = [[NSError alloc] initWithDomain:exception.name code:0 userInfo:exception.userInfo];
return NO;
}
}

@end

Don't forget to add this to your "*-Bridging-Header.h":

#import "ObjC.h"

How should I use NSSetUncaughtExceptionHandler in Swift

Update

With Swift 2, you can pass Swift functions and closures as C function pointer. See Martin R's answer below.

Original answer

You can't, as of Xcode 6 beta 6.

Swift does support passing around function pointers, but they're treated pretty much like opaque pointers. You can't neither define a C function pointer to a Swift function nor can you call a C function pointer in Swift.

That means you call NSSetUncaughtExceptionHandler() from Swift, but the handler must be implemented in Objective-C. You need a header file like this:

volatile void exceptionHandler(NSException *exception);
extern NSUncaughtExceptionHandler *exceptionHandlerPtr;

and in the implementation, you need something like this:

volatile void exceptionHandler(NSException *exception) {
// Do stuff
}
NSUncaughtExceptionHandler *exceptionHandlerPtr = &exceptionHandler;

After you imported the header file in the Swift bridging header, you can set up the exception handler as usual:

NSSetUncaughtExceptionHandler(exceptionHandlerPtr)

Is it possible to throw a RuntimeException in Swift without declaring it?

The error handling mechanism in Swift does not involve raising unchecked (runtime) exceptions. Instead, explicit error handling is required. Swift is certainly not the only recently designed language to go for this design – for instance Rust and Go also in their own ways also require explicitly describing the error paths in your code. In Objective-C the unchecked exception feature exists, but is largely used only for communicating programmer errors, with the notable exception of a few key Cocoa classes such as NSFileHandle which tends to catch people out.

Technically you do have the ability to raise Objective-C exceptions in Swift with the use of NSException(name: "SomeName", reason: "SomeReason", userInfo: nil).raise() as is explained in this excellent answer to this question, arguably a duplicate of your question. You really shouldn't raise NSExceptions though (not least because you have no Objective-C exception catching language feature available to you in Swift).

Why did they go with this design? Apple's "Error Handling in Swift 2.0" document explains the rationale clearly. Quoting from there:

This approach […] is very similar to the error handling model manually
implemented in Objective-C with the NSError convention. Notably, the
approach preserves these advantages of this convention:

  • Whether a method produces an error (or not) is an explicit part of its API contract.
  • Methods default to not producing errors unless they are explicitly marked.
  • The control flow within a function is still mostly explicit: a maintainer can tell exactly which statements can produce an error, and
    a simple inspection reveals how the function reacts to the error.
  • Throwing an error provides similar performance to allocating an error and returning it – it isn’t an expensive, table-based stack
    unwinding process. Cocoa APIs using standard NSError patterns can be
    imported into this world automatically. Other common patterns (e.g.
    CFError, errno) can be added to the model in future versions of Swift.

[…]

As to basic syntax, we decided to stick with the familiar language of
exception handling. […] by and large, error propagation in this
proposal works like it does in exception handling, and people are
inevitably going to make the connection.

Getting a Swift run-time error (NSException)

You have outlets defined for your view controller in a storyboard or .xib file. One of them is called "btnRoll" and was linked to the controller at some point. The matching property does not exist in code.

Possible reasons are: you deleted the code without unlinking the outlet or you have the wrong view controller defined as the view's owner.

Catch Objective-C exception in Swift

see this answer:

//
// ExceptionCatcher.h
//

#import <Foundation/Foundation.h>

NS_INLINE NSException * _Nullable tryBlock(void(^_Nonnull tryBlock)(void)) {
@try {
tryBlock();
}
@catch (NSException *exception) {
return exception;
}
return nil;
}


Related Topics



Leave a reply



Submit