如果您正在设计一个 Swift 函数(或方法),那么在处理错误时至少有 3 种选择:
选择 1:返回 Optional 类型
如果您的函数可能失败,并且经常发生这种情况,那么考虑返回一个 optional 类型变量。例如,在您的情况下,您的方法 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(result)
。调用者必须检查枚举并解包结果。可以使用
switch
来实现此操作:
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
中创建了一个Single View Application
。在StoryBoard
中的ViewController
中,我添加了3个TextField
(分别用于操作数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()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
@IBAction func addButton(sender : UIButton) {
var op1 = operand1.text
var op2 = operand2.text
if let answer = brain.add(op1, op2: op2)?.description {
result.text = answer
} else {
result.text = "No Result"
}
}
}
MathWhiz.swift
import UIKit
class MathWhiz: NSDecimalNumberBehaviors {
var badException = false
func roundingMode() -> NSRoundingMode {
return .RoundPlain
}
func scale() -> CShort {
return CShort(NSDecimalNoScale)
}
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
}
func add(op1: String, op2: String) -> NSDecimalNumber? {
let dn1 = NSDecimalNumber(string: op1)
let dn2 = NSDecimalNumber(string: op2)
badException = false
let dn3 = dn1.decimalNumberByAdding(dn2, withBehavior: self)
return badException ? nil : dn3
}
}
a + b > maxint
时会发生溢出。将b
从两边减去,得到a > maxint - b
。因此,在这种情况下返回nil
。这是针对整数的,但你可以理解这个概念。 - vacawamaNSDecimalNumberBehaviors
协议并实现exceptionDuringOperation()
方法的类,并使用NSDecimalNumber.setDefaultBehavior
将其设置为NSDecimalNumber
类的默认行为。这样,如果发生异常,就会调用你的exceptionsDuringOperation()
方法。然后你返回 nil。 - vacawama