如何在Swift中捕获“索引超出范围”?

时间:2016-05-14 05:11:13

标签: ios swift uitableview

我真的想在我的Swift代码中使用更简单的经典try catch块,但我找不到任何可以做到的东西。

我只需要:

try {
// some code that causes a crash.
}
catch {
// okay well that crashed, so lets ignore this block and move on.
}  

这是我的困境,当TableView重新加载新数据时,一些信息仍然存在于RAM中,它在tableView上调用didEndDisplayingCell,并且新的空数据源崩溃。

所以我经常抛出异常Index out of range

我试过这个:

func tableView(tableView: UITableView, didEndDisplayingCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {

    do {
        let imageMessageBody = msgSections[indexPath.section].msg[indexPath.row] as? ImageMessageBody
        let cell = tableView.dequeueReusableCellWithIdentifier("ImageUploadCell", forIndexPath: indexPath) as! ImageCell
        cell.willEndDisplayingCell()
    } catch {
        print("Swift try catch is confusing...")
    }
}

我也试过这个:

func tableView(tableView: UITableView, didEndDisplayingCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    print(indexPath.section)
    print(indexPath.row)

    if msgSections.count != 0 {
        if let msg = msgSections[indexPath.section].msg[indexPath.row] as? ImageMessageBody {
            let cell = tableView.dequeueReusableCellWithIdentifier("ImageUploadCell", forIndexPath: indexPath) as! ImageCell
            cell.willEndDisplayingCell()
        }
    }
}

这是一个非常低优先级的代码块,我浪费了大量的时间进行试验和错误,找出swift中构建的错误处理程序,当我有大量的场景时,看起来非常独特的情况这个代码可能会崩溃,它不会对用户体验产生任何影响。

简而言之,我不需要任何花哨的东西,但Swift似乎有非常具体的错误处理程序,这些错误处理程序根据我是从函数返回值获取值还是从数组索引中获取可能不存在的值而有所不同

像其他流行的编程语言一样,是否有一个关于Swift的简单尝试?

5 个答案:

答案 0 :(得分:37)

正如评论和其他答案中所建议的那样,最好避免这种情况。但是,在某些情况下,您可能需要检查数组中是否存在项目以及是否确实安全地返回该项目。为此,您可以使用以下Array扩展来安全返回数组项。

Swift 3

extension Collection where Indices.Iterator.Element == Index {
    subscript (safe index: Index) -> Generator.Element? {
        return indices.contains(index) ? self[index] : nil
    }
}

Swift 2

extension Array {
    subscript (safe index: Int) -> Element? {
        return indices ~= index ? self[index] : nil
    }
}
  • 这样你永远不会 Index out of range
  • 您必须检查该项目是否为nil

请参阅this question了解更多

  

在Xcode 8.3.2中的Playground中尝试Swift3代码仍然会导致a   "碰撞"当我让ar = [1,3,4]时,让v = ar [5]。为什么? - 托马斯   Tempelmann 5月17日17:40

您必须使用我们的自定义下标,而不是let v = ar[5],它将是let v = ar[safe: 5]

默认从数组中获取值。

let boo = foo[index]

添加使用自定义下标。

let boo = fee[safe: index]

// And we can warp the result using guard to keep the code going without throwing the exception.
guard let boo = foo[safe: index] else {
  return
}

答案 1 :(得分:26)

Swift的Error Handlingdo / try / catch 运行时异常<的解决方案 / strong>喜欢&#34;索引超出范围&#34;。

运行时异常(您可能还会看到这些称为陷阱致命错误断言失败等)是程序员的标志错误。除了在-Ounchecked版本中,Swift通常会保证这些崩溃您的程序,而不是继续以错误/未定义的状态执行。这些类型的崩溃可能来自强制解包!,隐式展开,误用unowned引用,整数运算/转换溢出,fatalError() s和precondition() s和assert()等等(不幸的是,Objective-C例外。)

解决方案是避免这些情况。在您的情况下,检查数组的边界:

if indexPath.section < msgSections.count && indexPath.row < msgSections[indexPath.section].msg.count {
    let msg = msgSections[indexPath.section].msg[indexPath.row]
    // ...
}

(或者,正如rmaddy在评论中所说 - 调查为什么这个问题正在发生!它真的不应该发生。)

答案 2 :(得分:9)

斯威夫特4:

extension Collection where Indices.Iterator.Element == Index {
    subscript (exist index: Index) -> Iterator.Element? {
        return indices.contains(index) ? self[index] : nil
    }
}

<强>用法

var index :Int = 6 // or whatever number you need
if let _ = myArray[exist: index] {
   // do stuff
}

var index :Int = 6 // or whatever number you need
guard let _ = myArray[exist: index] else { return }

答案 3 :(得分:1)

您可以尝试不同的方法。肯定会工作!

if msgSections != nil {
    for msg in msgSections[indexPath.section] {
        if msgSections[indexPath.section].index(of: msg) == indexPath.row {
            (Code)
        }
}

答案 4 :(得分:0)

Swift 5 中的

This答案变为:

extension Collection where Indices.Iterator.Element == Index {
    subscript (safe index: Index) -> Iterator.Element? {
        return indices.contains(index) ? self[index] : nil
    }
}

否则,在 Swift 4 中,可以在关联类型上包含子句,并且可以变为:

extension Collection {
    subscript (safe index: Index) -> Element? {
        return indices.contains(index) ? self[index] : nil
    }
}