在swift中捕获无效用户输入的异常

时间:2014-07-12 06:47:26

标签: ios cocoa-touch exception-handling swift nsexpression

我正在尝试这个计算器代码。如何处理用户无效的输入?

//答案:将标题桥接到Objective-C // https://github.com/kongtomorrow/TryCatchFinally-Swift

这是同样的问题但是在objc但是我想在swift中这样做。 Catching NSInvalidArgumentException from NSExpression

我想要展示的是一条消息,如果它不起作用,但现在当用户没有输入正确的格式时我会收到异常。

import Foundation

var equation:NSString = "60****2"  // This gives a NSInvalidArgumentException', 
let expr = NSExpression(format: equation) // reason: 'Unable to parse the format string
if let result = expr.expressionValueWithObject(nil, context: nil) as? NSNumber {
    let x = result.doubleValue
    println(x)
} else {
    println("failed")
}

3 个答案:

答案 0 :(得分:10)

更多" Swifty"溶液:

@implementation TryCatch

+ (BOOL)tryBlock:(void(^)())tryBlock
           error:(NSError **)error
{
    @try {
        tryBlock ? tryBlock() : nil;
    }
    @catch (NSException *exception) {
        if (error) {
            *error = [NSError errorWithDomain:@"com.something"
                                         code:42
                                     userInfo:@{NSLocalizedDescriptionKey: exception.name}];
        }
        return NO;
    }
    return YES;
}

@end

这将生成Swift代码:

class func tryBlock((() -> Void)!) throws

您可以将其与try

一起使用
do {
    try TryCatch.tryBlock {
        let expr = NSExpression(format: "60****2")
        ...
    }
} catch {
    // Handle error here
}

答案 1 :(得分:7)

这仍然是Swift 2中的一个问题。如上所述,最好的解决方案是使用桥接头并捕获Objective C中的NSException。

https://medium.com/swift-programming/adding-try-catch-to-swift-71ab27bcb5b8描述了一个很好的解决方案,但确切的代码并没有在Swift 2中编译,因为trycatch现在是保留关键字。您需要更改方法签名以解决此问题。这是一个例子:

// https://medium.com/swift-programming/adding-try-catch-to-swift-71ab27bcb5b8

@interface TryCatch : NSObject

+ (void)tryBlock:(void (^)())try catchBlock:(void (^)(NSException *))catch finallyBlock:(void (^)())finally;

@end

@implementation TryCatch

+ (void)tryBlock:(void (^)())try catchBlock:(void (^)(NSException *))catch finallyBlock:(void (^)())finally {
    @try {
        try ? try() : nil;
    }
    @catch (NSException *e) {
        catch ? catch(e) : nil;
    }
    @finally {
        finally ? finally() : nil;
    }
}

@end

答案 2 :(得分:1)

https://github.com/kongtomorrow/TryCatchFinally-Swift编辑一个不错的解决方案:

首先创建TryCatch.h& TryCatch.m并将它们连接到Swift:

<强> TryCatch.h

#import <Foundation/Foundation.h>

void tryCatch(void(^tryBlock)(), void(^catchBlock)(NSException *e), void(^finallyBlock)());

<强> TryCatch.m

#import <Foundation/Foundation.h>

void tryCatch(void(^tryBlock)(), void(^catchBlock)(NSException *e), void(^finallyBlock)()) {
    @try {
        tryBlock();
    }
    @catch (NSException *exception) {
        catchBlock(exception);
    }
    @finally {
        finallyBlock();
    }
}

然后在Swift中创建类TryCatch

func `try`(`try`:()->()) -> TryCatch {
    return TryCatch(`try`)
}
class TryCatch {
    let tryFunc : ()->()
    var catchFunc = { (e:NSException!)->() in return }
    var finallyFunc : ()->() = {}

    init(_ `try`:()->()) {
        tryFunc = `try`
    }

    func `catch`(`catch`:(NSException)->()) -> TryCatch {
        // objc bridging needs NSException!, not NSException as we'd like to expose to clients.
        catchFunc = { (e:NSException!) in `catch`(e) }
        return self
    }

    func finally(finally:()->()) {
        finallyFunc = finally
    }

    deinit {
        tryCatch(tryFunc, catchFunc, finallyFunc)
    }
}

最后,使用它! :)

`try` {
    let expn = NSExpression(format: "60****2")

    //let resultFloat = expn.expressionValueWithObject(nil, context: nil).floatValue
    // Other things...
    }.`catch` { e in
        // Handle error here...
        print("Error: \(e)")
}