例如,我可以使用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没有异常处理,但是这个问题正在寻找一种很好的方式来处理这个问题,就像语言创建者认为应该完成的那样.
有没有一种推荐的方法来处理这个问题而不必编写我自己的代码来检查溢出,下溢,精度损失等等?我想要NSDecimalNumberHandler为我做这件事.
解决方法
选择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 } }
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。