异常处理 – 异常处理的Swift异常
在通过论坛和
Swift文档进行细读之后(不完全,我承认),似乎在Swift中我们鼓励编写更安全的代码,而不是try-catch机制.鉴于此,我对一个示例API有疑问,并想学习如何更安全地处理这种情况:
例如,我可以使用NSDecimalNumberHandler创建以下类: class MathWhiz { init() { let defaultBehavior: NSDecimalNumberHandler = NSDecimalNumberHandler.defaultDecimalNumberHandler() } func add(op1: String,op2: String) ->NSDecimalNumber { return NSDecimalNumber.decimalNumberWithString(op1).decimalNumberByAdding(NSDecimalNumber.decimalNumberWithString(op2)) } } 如果我使用以下内容,我会得到一个数字: let brain = MathWhiz() brain.add("1",op2: "1e127") 但是,如果我导致溢出异常,: brain.add("1",op2: "1e128") 我会按预期崩溃程序. 所以,我的问题是,API引发异常,但我不在这里处理它们.还有其他帖子指出Swift没有异常处理,但是这个问题正在寻找一种很好的方式来处理这个问题,就像语言创建者认为应该完成的那样. 解决方法
如果您在Swift中设计函数(或方法),则至少有3个选项来处理错误:
选择1:返回可选类型 如果您的函数可能失败,并且这种情况经常发生,那么请考虑返回一个可选的类型变量.例如,在您的情况下,您的方法add可以返回NSDecimalNumber?而不是普通的NSDecimalNumber.在这种情况下,您的方法将检查可能出错的所有内容,并在这些情况下返回nil.溢出和下溢将返回nil,并且所有其他情况将返回NSDecimalNumber.调用者必须检查和解包可选的NSDecimalNumber,如下所示: let brain = MathWhiz() if let sum = brain.add("1",op2: "1e127") { println("the result was (sum)") } else println("something went wrong with MathWhiz add") } 选择2:返回枚举类型 如果要返回有关出错的更多信息,可以创建一个枚举类型,其中包含每个错误的值和一个嵌入答案的成功值.例如,您可以这样做: enum MathWhizResult { case Overflow case Underflow case Success(NSDecimalNumber) } 然后将定义add以返回MathWhizResult: func add(op1: String,op2: String) -> MathWhizResult 如果出现错误,add将返回.Overflow或.Underflow.如果成功,add将返回Success(结果).调用者必须检查枚举并解压缩结果.可以使用一个开关: switch (brain.add("1",op2: "1e128")) { case .Overflow println("darn,it overflowed") case .Underflow println("underflow condition happened") case .Success(let answer) println("the result was (answer)" } 选择3:选择不明确处理错误 在前两个选项中解压缩结果对于非常罕见的错误可能是过多的开销.您可以选择仅返回结果,并让调用者处理下溢或溢出情况的可能性.在这种情况下,他们必须在调用add之前自己检查这些条件.好处是,他们知道他们的程序永远不会导致下溢或溢出(因为他们正在处理单个数字的数字),他们没有负担解压缩结果. 我创建了一个小应用程序来演示如何使用NSDecimalNumbers执行此操作.我在Xcode中创建了一个单视图应用程序.在StoryBoard的ViewController中,我添加了3个TextFields(操作数1,操作数2和结果各一个)和我标记的Button. ViewController.swift import UIKit class ViewController: UIViewController { @IBOutlet var operand1 : UITextField! @IBOutlet var operand2 : UITextField! @IBOutlet var result : UITextField! var brain = MathWhiz() override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view,typically from a nib. } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } @IBAction func addButton(sender : UIButton) { var op1 = operand1.text var op2 = operand2.text // Perform the add with the contents of the operand fields. // Print the answer,or "No Result" if add returns nil. if let answer = brain.add(op1,op2: op2)?.description { result.text = answer } else { result.text = "No Result" } } } MathWhiz.swift import UIKit // Declare that we implement NSDecimalNumberBehaviors so that we can handle // exceptions without them being raised. class MathWhiz: NSDecimalNumberBehaviors { var badException = false // Required function of NSDecimalNumberBehaviors protocol func roundingMode() -> NSRoundingMode { return .RoundPlain } // Required function of NSDecimalNumberBehaviors protocol func scale() -> CShort { return CShort(NSDecimalNoScale) } // Required function of NSDecimalNumberBehaviors protocol // Here we process the exceptions func exceptionDuringOperation(operation: Selector,error: NSCalculationError,leftOperand: NSDecimalNumber,rightOperand: NSDecimalNumber) -> NSDecimalNumber? { var errorstr = "" switch(error) { case .NoError: errorstr = "NoError" case .LossOfPrecision: errorstr = "LossOfPrecision" case .Underflow: errorstr = "Underflow" badException = true case .Overflow: errorstr = "Overflow" badException = true case .DivideByZero: errorstr = "DivideByZero" badException = true } println("Exception called for operation (operation) -> (errorstr)") return nil } // Add two numbers represented by the strings op1 and op2. Return nil // if a bad exception occurs. func add(op1: String,op2: String) -> NSDecimalNumber? { let dn1 = NSDecimalNumber(string: op1) let dn2 = NSDecimalNumber(string: op2) // Init badException to false. It will be set to true if an // overflow,underflow,or divide by zero exception occur. badException = false // Add the NSDecimalNumbers,passing ourselves as the implementor // of the NSDecimalNumbersBehaviors protocol. let dn3 = dn1.decimalNumberByAdding(dn2,withBehavior: self) // Return nil if a bad exception happened,otherwise return the result // of the add. return badException ? nil : dn3 } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |