【问题标题】:How to catch an NSRangeException with do...catch?如何使用 do...catch 捕获 NSRangeException?
【发布时间】:2015-12-29 12:38:18
【问题描述】:

我正在将这段 Java 代码翻译成 swift:

for (int i = 0 ; i < groups.length ; i++) {
    try {
        groups[i] = integerPart.substring (i * 3, i * 3 + 3);
    } catch (IndexOutOfBoundsException ex) {
        groups[i] = integerPart.substring (i * 3);
    }
    groups[i] = new StringBuilder (groups[i]).reverse ().toString ();
    groups[i] = get1To3DigitString (groups[i]) + " " + getTheWord (i) + " ";
}

注意:

  • integerPart 是一个字符串。
  • groups 是一个字符串数组。
  • 请忽略get1To3DigitStringgetTheWord

我的想法和尝试:

由于 swift 的字符串真的很烦人(不能用Int 索引),我决定使用NSStringsubstringFromIndexsubstringWithRange 方法来做substring Java 方法。所以我写了这两种方法来帮助我:

func substring (s: String, start: Int, end: Int) throws -> String{
    let ns = NSString(string: s)
    return String(ns.substringWithRange(NSRange(start..<end)))
}

func substring (s: String, start: Int) -> String {
    let ns = NSString(string: s)
    return String(ns.substringFromIndex(start))
}

我知道NSString 中的两个子字符串方法会抛出一个NSRangeException,就像Java 的IndexOutOfBoundsException 一样。所以这是我的快速代码:

for var i = 0 ; i < groups.count ; i++ {
    do {
        try groups[i] = substring(integerPart, start: i * 3, end: i * 3 + 3)
    } catch NSRangeException {
        groups[i] = substring(integerPart, start: i * 3)
    }
    groups[i] = String (groups[i].characters.reverse())
    groups[i] = get1To3DigitString (groups[i]) + " " + getTheWord (i) + " "
}

我收到一条错误消息,提示捕获模式与 ErrorType 不匹配!我认为它确实匹配ErrorType,因为如果不匹配,我应该如何捕获异常?于是我把NSRangeException这个词删了。

我想如果在substring 中抛出异常,我会在catch 部分捕获它。但是当我测试它时,try 行发生了异常!我想这是因为我写错了 catch 模式。

我应该如何捕捉NSRangeException

【问题讨论】:

  • 而且我知道 NSString 中的两个子字符串方法会引发 NSRangeException - 是吗?
  • Swifts try/catch 用于与throw 一起抛出的 Swift 错误。这与运行时错误或 NSException 完全无关,您在 Swift 中无法捕获它们。
  • 我测试过了。他们真的做到了!我试过substring("Hello", start: 1, end: 10)@luk2302

标签: java swift exception exception-handling


【解决方案1】:

就像在 Java 中一样,您永远不会在 Swift 或 Objective-C 中遇到 IndexOutOfBoundsException 您永远不会遇到 NSRangeException

这些异常是由于您作为开发人员搞砸了,而不是应用程序或某些外部因素,或者是用户的输入。在Java 中有术语已检查的异常未检查的异常。第一个你可以并且应该甚至必须捕捉,第二个发生在运行时,主要是程序中的错误信号。

在长度为 5 的字符串之前,您绝对不能将其子串化,直到它的第十个字符 - 这是您作为开发人员可以并且必须知道和注意的事情。如果您这样做,程序应该崩溃。

我不确定你是否真的可以收到NSRangeException - 如果你不能做到,我会很高兴。对于常规错误,您可以定义自定义错误类型:

enum LevelParsingException : ErrorType {
    case MalformedJson
    case InvalidLevelContent
}

那么你有一些函数可能会抛出它们:

func parseLevel() throws {
    guard someCondition {
        throw LevelParsingException.InvalidLevelContent
    }
}

然后您调用该方法并捕获您知道可能出现的所有不同错误:

func call() {
    do {
        try parseLevel()
    } catch LevelParsingException.InvalidLevelContent {
        print("something")
    } catch  {
        print("something else")
    }
}

apple docs的解释都比较好。

【讨论】:

  • 你的意思是我应该先检查substring的参数是否在范围内,然后调用它?
  • @Sweeper 是的,要么检查它 要么 只需确保您作为开发人员不要以错误的方式使用该方法。
  • 我认为你应该回答最初的问题,而不是说我们搞砸了 :) 如果 UIKit 抛出这个异常而我必须处理它怎么办? removeObserver 方法抛出这个(KVO),我无法检查我的对象是否仍然注册到该属性。
  • @batu 如果抛出异常,您“搞砸了”/引入了一个错误,因为您错过了取消注册之前注册的对象。如果您一开始就正确编码,则没有需要捕获这些异常 - 只有在您没有正确检查边缘情况和/或错过一些呼叫等情况下才会抛出这些异常。无需检查如果您的对象仍在注册 - 如果您注册过一次,则必须取消注册一次。
  • 你知道,UIPageViewController 是有问题的。对于某些“边缘”情况,它不会调用它的子视图控制器的 viewDidDisappear 方法。我通常在那里注销。但我需要处理那些“边缘”案例。我看你对自己很有信心,但我认为这有点过分了。你没有给出解决方案,而是坚持我搞砸了。错误发生,有时您需要一个安全网。这就是编程的现实。
猜你喜欢
  • 1970-01-01
  • 2016-05-21
  • 1970-01-01
  • 2016-09-07
  • 2021-01-02
  • 2017-12-02
  • 1970-01-01
  • 2011-02-15
  • 1970-01-01
相关资源
最近更新 更多