加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

异常处理 – 异常处理的Swift异常

发布时间:2020-12-14 04:44:59 所属栏目:百科 来源:网络整理
导读:在通过论坛和 Swift文档进行细读之后(不完全,我承认),似乎在Swift中我们鼓励编写更安全的代码,而不是try-catch机制.鉴于此,我对一个示例API有疑问,并想学习如何更安全地处理这种情况: 例如,我可以使用NSDecimalNumberHandler创建以下类: class MathWhiz {
在通过论坛和 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没有异常处理,但是这个问题正在寻找一种很好的方式来处理这个问题,就像语言创建者认为应该完成的那样.
有没有一种推荐的方法来处理这个问题而不必编写我自己的代码来检查溢出,下溢,精度损失等等?我想要NSDecimalNumberHandler为我做这件事.

解决方法

如果您在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
    }
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读