How can I throw an NSError from a Swift class and catch it in an Objective-C class?

我的未来我决定 提交于 2020-01-24 22:11:31

问题


I need to implement a try-catch structure in Objective-C to handle Swift thrown NSErrors.

I've written an NetService manager with Swift code and I am implementing it on an already existent Objective-C UI.

However, whenever I throw an error from my Swift class, the try-catch structure fails to catch the error and proceeds to the finally block.

Swift error definition:

enum NEONetServiceErrors: Int
{
    case requestMadeWithoutIp
}

struct NEONetServiceErrorStrings
{
    let requestMadeWithoutIp = ["NEONetService Error: Request made without IP": NEONetServiceErrors.requestMadeWithoutIp]
}

Swift error throwing:

@objc func requestHelloPage() throws
{
    if serviceiPAddress != nil
    {
        makeHelloRequest()
    }
    else
    {
        throw NSError(domain: errorStrings.domain, code: NEONetServiceErrors.requestMadeWithoutIp.rawValue, userInfo:errorStrings.requestMadeWithoutIp)
    }
}

Objective-C properties:

@property NEONetServiceManager* netServiceManager;
@property NSError* _Nullable __autoreleasing * _Nullable netServiceError;

Objective-C error handling:

- (IBAction)pressUpdateButton:(id)sender
{
    @try
    {
        [self.netServiceManager requestHelloPageAndReturnError: self.netServiceError];
    }
    @catch (NSException *exception)
    {
        NSLog(@"Throwing");
    }
    @finally
    {
        NSLog(@"Finally");
    }
}

Output:

2019-10-18 14:47:03.289268-0300 NEOFirmUpdate[16533:2389800] Start
2019-10-18 14:47:03.292696-0300 NEOFirmUpdate[16533:2389800] Finally

Could you help me figure out what I am doing wrong with my error-handling?


回答1:


The problem is that a Swift Error / Objective-C NSError is not an NSException. You are configured to catch NSExceptions but that is irrelevant.

The way to "catch" an NSError in Objective-C when Swift throws an Error is by indirection with the NSError** parameter, just as it always has been.

NSError* err = nil;
BOOL ok = [self.netServiceManager requestHelloPageAndReturnError:&err];
if (ok) {
    // proceed normally
} else {
    // you got an error, it is sitting in `err`
}

(Notice how Swift supplies a BOOL result exactly so you can implement the correct pattern.)




回答2:


That's because you're using objective-c exceptions there, and not actually checking for an error. To check for errors in objective-c, you pass a reference to your pointer and your function will fill that error out if there was an issue.

NSError *serviceError = nil;
[self.netServiceManager requestHelloPageAndReturnError:&serviceError];
if (serviceError) {
    // there was a problem
}

If this is an asynchronous call, you'll need to do this in a closure instead:

NSError *serviceError = nil;
[self.netServiceManager requestHelloPage:^(NSError *error) {
    if (error) {
        // there was a problem
    }
}];



回答3:


In your Objective-C code you are Catching and NSException, not an NSError

Swift automatically bridges between the Error type and the NSError class. Objective-C methods that produce errors are imported as Swift methods that throw, and Swift methods that throw are imported as Objective-C methods that produce errors, according to Objective-C error conventions.

for more information you can click here



来源:https://stackoverflow.com/questions/58455883/how-can-i-throw-an-nserror-from-a-swift-class-and-catch-it-in-an-objective-c-cla

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!