我想验证用户创建的表达式(例如“2 + 2”,“5 + 7”或更复杂)。我使用NSExpression类来解析和计算这个表达式。这是我的Playground代码:
import UIKit
let string = "2+2"
var ex:NSExpression?
do {
ex = NSExpression(format: string)
}
catch {
print("String is not valid expression")
}
if let result = ex?.expressionValue(with: nil, context: nil) as! NSNumber? {
print("result is \(result)")
}
当我使用有效表达式(“2 + 2”)时 - 我得到了结果。但有时用户可以提供错误的字符串(例如“2+”)。有了这个字符串我的应用程序崩溃了:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unable to parse the format string "2+ == 1"'
我不明白如何捕获此异常以及为什么上面的代码不会这样做。现在我使用Objective C类(使用相同的逻辑),从我的swift代码调用此方法,并在该类中我真的可以捕获这样的异常:
+(NSNumber *)solveExpression:(NSString *)string
{
id value;
@try {
NSExpression *ex = [NSExpression expressionWithFormat:string];
value = [ex expressionValueWithObject:nil context:nil];
}
@catch (NSException *e) { }
return value;
}
这有效,我可以获得正确的解析状态(nil表示表达式问题)和结果(NSNumber),但我真的想要了解如何在Swift中正确完成所有这些事情。
答案 0 :(得分:3)
本书使用Swift与Cocoa和Objective-C empty pseudo class:
尽管Swift错误处理类似于Objective-C中的异常处理,但它完全是独立的功能。如果Objective-C方法在运行时抛出异常,则Swift会触发运行时错误。 无法直接在Swift中从Objective-C异常中恢复。任何异常处理行为都必须在Swift使用的Objective-C代码中实现。
[我的大胆]
刚刚浏览了NSExpression
的引用,我无法看到解决问题的简单方法。上面的引用建议编写一些Objective-C代码来完成它。最简单的方法可能是创建一个C函数:
宣言:
extern NSExpression* _Nullable makeExpression(NSString* format _Nonnull);
定义
NSExpression* _Nullable makeExpression(NSString* format _Nonnull)
{
NSExpression* ret = nil;
@try
{
// create and assign the expression to ret
}
@catch(NSException* e)
{
// ignore
}
return ret;
}
对于出错的表达式,函数返回nil。
您可以添加NSError**
参数,以便在出现故障时使用。您也可以在NSExpression
上的类别中创建一个方法,然后NSError模式中的错误/填充的返回nil可能会作为Swift抛出方法导入Swift。
顺便说一句,我应该说,Objective-C异常并不能保证让你的程序保持一致状态。在这种情况下,手指越过它是可以的。
答案 1 :(得分:2)
NSInvalidArgumentException
不是一个可捕获的错误。当你发现这个异常时,Apple并不能保证你的程序处于正确的状态,并且可能会出现问题。
在将字符串传递给方法之前,您应该使用其他一些机制来检查字符串是否有效。