【问题标题】:Catch an exception for invalid user input in swift快速捕获无效用户输入的异常
【发布时间】:2014-09-02 19:52:50
【问题描述】:

我正在尝试这段代码,它是一个计算器。如何处理来自用户的无效输入?

//ANSWER: 将标头桥接到 Objective-C// https://github.com/kongtomorrow/TryCatchFinally-Swift

这是同样的问题,但在 objc 中,但我想快速执行此操作。 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")
}

【问题讨论】:

  • 为什么不使用正则表达式匹配来查看可接受的方程列表。你应该考虑automation theory来理解计算。
  • 目前在 Swift 中似乎不可能捕获异常,比较 stackoverflow.com/questions/24023112/… 和链接的问题。 - 不幸的是,NSExpression(和其他 Foundation 类)没有遵循 Apple 的建议,即使用错误参数而不是抛出异常。
  • 这是苹果用于 Mac 聚光灯内联计算的方法。我想知道在将字符串传递给表达式之前是否可以访问内置解析器来检查字符串。
  • 我找到了这个有效的桥接文件github.com/kongtomorrow/TryCatchFinally-Swift

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


【解决方案1】:

更多“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
}

【讨论】:

  • 建议的解决方法不适用于 Swift 构建的框架。仍然希望有一个真正的解决方案。
  • @WimHaanstra 我们的 Swift 框架中有这个:github.com/eggheadgames/SwiftTryCatch
  • 谢谢,现在可以使用了。将标题公开,现在它可以工作了(?)
  • @WimHaanstra 不客气!你的意思是TryCatch 标头,还是SwiftTryCatch
【解决方案2】:

这在 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

【讨论】:

    【解决方案3】:

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

    首先创建 TryCatch.hTryCatch.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)")
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-19
      • 2018-04-18
      • 2013-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多