我如何捕捉“索引超出范围"?在斯威夫特? [英] How do I catch "Index out of range" in Swift?

查看:19
本文介绍了我如何捕捉“索引超出范围"?在斯威夫特?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

我只需要:

尝试{//一些导致崩溃的代码.}抓住 {//好吧,崩溃了,所以让我们忽略这个块并继续前进.}

这是我的困境,当 TableView 用新数据重新加载时,一些信息仍然位于 RAM 中,它在具有新空数据源的 tableView 上调用 didEndDisplayingCell 导致崩溃.

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

我已经试过了:

func tableView(tableView: UITableView, didEndDisplayingCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {做 {让 imageMes​​sageBody = msgSections[indexPath.section].msg[indexPath.row] 作为?图像消息体let cell = tableView.dequeueReusableCellWithIdentifier("ImageUploadCell", forIndexPath: indexPath) as!图像单元cell.willEndDisplayingCell()} 抓住 {print("Swift try catch 令人困惑...")}}

我也试过这个:

func tableView(tableView: UITableView, didEndDisplayingCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {打印(索引路径.部分)打印(indexPath.row)如果 msgSections.count != 0 {如果让 msg = msgSections[indexPath.section].msg[indexPath.row] 作为?ImageMes​​sageBody {let cell = tableView.dequeueReusableCellWithIdentifier("ImageUploadCell", forIndexPath: indexPath) as!图像单元cell.willEndDisplayingCell()}}}

这是一个非常低优先级的代码块,当我有大量场景时,我浪费了大量时间进行反复试验,以确定 swift 中内置的哪个错误处理程序适用于似乎非常独特的情况这是一个代码可能会崩溃并且不会对用户体验产生任何影响的地方.

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

是否有像其他流行的编程语言一样对 Swift 进行简单的尝试?

解决方案

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

Swift 5

extension Collection where Indices.Iterator.Element == Index {下标(安全索引:索引)->迭代器.元素?{返回 index.contains(index) ?自我[索引]:无}}

Generator.Element 变成 Iterator.Element

Swift 3

extension Collection where Indices.Iterator.Element == Index {下标(安全索引:索引)->生成器.元素?{返回 index.contains(index) ?自我[索引]:无}}

Swift 2

扩展数组{下标(安全索引:Int)->元素?{返回索引 ~= 索引 ?自我[索引]:无}}

  • 这样你就永远不会命中 索引超出范围
  • 您必须检查该项目是否为 nil

参考这个问题了解更多


<块引用>

在 Xcode 8.3.2 的 Playground 中尝试 Swift3 代码仍然导致崩溃"当我让 ar = [1,3,4],然后让 v = ar[5].为什么?– 托马斯滕珀尔曼 5 月 17 日 17:40

你必须使用我们定制的下标,所以不是let v = ar[5],而是let v = ar[safe: 5].>

默认从数组中获取值.

let boo = foo[index]

添加使用自定义下标.

let boo = fee[safe: index]//并且我们可以使用 guard 来扭曲结果以保持代码运行而不抛出异常.守卫 let boo = foo[safe: index] else {返回}

I would really like to use a more simple classic try catch block in my Swift code but I can't find anything that does it.

I just need:

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

Here's my dilema, when the TableView is reloaded with new data, some information is still siting in RAM which calls didEndDisplayingCell on a tableView with a freshly empty datasource to crash.

So I frequently thrown the exception Index out of range

I've tried this:

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...")
    }
}

I've also tried this:

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()
        }
    }
}

This is a very low priority block of code, and I have wasted a lot of time with trial and error figuring out which error handler built into swift works for what seems to be extremely unique situations when I have tons of scenarios just like this one where the code can crash and it will not have any effect on the user experience.

In short, I don't need anything fancy but Swift seems to have extremely specific error handlers that differ based on whether I'm getting a value from a functions return value or getting a value from an array's index which may not exist.

Is there a simple try catch on Swift like every other popular programming language?

解决方案

As suggested in comments and other answers it is better to avoid this kind of situations. However, in some cases you might want to check if an item exists in an array and if it does safely return it. For this you can use the below Array extension for safely returning an array item.

Swift 5

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

Generator.Element becomes Iterator.Element

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
    }
}

  • This way you'll never hit Index out of range
  • You'll have to check if the item is nil

refer this question for more


Trying the Swift3 code in a Playground in Xcode 8.3.2 still leads to a "crash" when I do let ar = [1,3,4], then let v = ar[5]. Why? – Thomas Tempelmann May 17 at 17:40

You have to use our customized subscript so instead of let v = ar[5], it wll be let v = ar[safe: 5].

Default getting value from array.

let boo = foo[index]

Add use the customized subscript.

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
}

这篇关于我如何捕捉“索引超出范围"?在斯威夫特?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆