我想验证用户创建的表达式(如“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中正确完成所有这些事情.
这就是使用Swift与Cocoa和Objective-C has to say的书:Although Swift error handling resembles exception handling in Objective-C, it is entirely separate functionality. If an Objective-C method throws an exception during runtime, Swift triggers a runtime error. There is no way to recover from Objective-C exceptions directly in Swift. Any exception handling behavior must be implemented in Objective-C code used by Swift.
[我的大胆]
刚刚浏览了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异常并不能保证让程序保持一致状态.在这种情况下,手指越过它是可以的.