Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios “我怎样才能抓住”这句话;“索引超出范围”;斯威夫特?_Ios_Swift_Uitableview - Fatal编程技术网

Ios “我怎样才能抓住”这句话;“索引超出范围”;斯威夫特?

Ios “我怎样才能抓住”这句话;“索引超出范围”;斯威夫特?,ios,swift,uitableview,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上调用DiEndDi

我真的很想在我的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上调用
DiEndDisplayingCell
,使其崩溃

所以我经常抛出异常
索引超出范围

我试过这个:

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()
        }
    }
}
我也试过:

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有一个简单的try-catch吗?

Swift(
do
/
try
/
catch
)是而不是运行时异常的解决方案,比如“索引超出范围”

运行时异常(您可能还会看到称为陷阱、致命错误、断言失败等)是程序员错误的标志。除了在
-unchecked
构建中,Swift通常保证这些构建将使程序崩溃,而不是继续在错误/未定义的状态下执行。使用
强制展开可能会导致此类崩溃
、隐式展开、滥用
无主
引用、溢出的整数操作/转换、
fatalError()
s和
Premission()
s和
assert()
s等(不幸的是,还有Objective-C异常)

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

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

(或者,正如rmaddy在评论中所说,调查这个问题发生的原因!它根本不应该发生。)

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

Swift 5

extension Collection where Indices.Iterator.Element == Index {
    subscript (safe index: Index) -> Iterator.Element? {
        return indices.contains(index) ? self[index] : nil
    }
}
元素变成迭代器元素

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
    }
}
  • 这样,您将永远不会点击
    索引超出范围
  • 您必须检查项目是否为
    nil
参考更多



在Xcode 8.3.2的操场上尝试Swift3代码仍然会导致 “crash”当我设ar=[1,3,4],然后设v=ar[5]。为什么托马斯 坦佩尔曼5月17日17:40

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

从数组中获取默认值

让boo=foo[index]
添加并使用自定义的下标

let boo=fee[safe:index]
//我们可以使用guard扭曲结果,使代码继续运行,而不会引发异常。
guard let boo=foo[safe:index]else{
返回
}

您可以尝试不同的方法。一定会成功的

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

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

在Swift 5中回答以下问题:

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

看来你在试图解决错误的问题。您应该解决重新加载表视图后,为什么对旧数据调用
didendisplaycell
的问题。那没有任何意义。为什么会这样?是否在后台线程上更新表视图的数据?这是一个可能的问题。通常不要自己调用包含
did
will
should
的委托方法。它们是由框架调用的。在按索引访问之前,您必须通过检查数组计数来处理此问题。您是否已了解在您的案例中发生这种情况的原因?我希望这是默认行为,但对我来说不起作用。你能解释一下它是如何工作的吗?这里的~indexs~是什么?当不需要选项时,它会在上下文中引入选项。最好的解决方案是让你的应用程序崩溃。索引越界是程序员错误的标志。你不应该忽视那个标志,或者试图用一个可选的符号来吞下它。尽量避免它。@Sulthan,索引越界可能不是由于编程错误造成的。例如,您正在处理作为程序员无法控制的动态数据。语言应该保护程序不以胎儿运行时错误结束。与其他语言相比,这是糟糕的语言设计和Swift婴儿期的标志。希望在将来的版本中能改变这一点。在Xcode 8.3.2的操场上尝试Swift3代码仍然会导致“崩溃”,当我这样做时
让ar=[1,3,4]
,然后
让v=ar[5]
。为什么?