¿Cómo puedo ver “Índice fuera de rango” en Swift?

Realmente me gustaría utilizar un bloque de captura try clásico más simple en mi código Swift, pero no puedo encontrar nada que lo haga.

Yo solo necesito:

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

Aquí está mi dilema, cuando el TableView se recarga con datos nuevos, todavía hay algo de información en la RAM que llama a didEndDisplayingCell en un tableView con un datasource recientemente vacío para colgar.

Así que con frecuencia arrojo el Index out of range excepción Index out of range

He intentado esto:

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

También he intentado esto:

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

Este es un bloque de código de prioridad muy baja, y he perdido mucho tiempo con el método de prueba y error para descubrir qué controlador de errores incorporado en Swift funciona para lo que parecen ser situaciones extremadamente únicas cuando tengo un montón de escenarios como este donde el código puede bloquearse y no tendrá ningún efecto en la experiencia del usuario.

En resumen, no necesito nada sofisticado, pero Swift parece tener manejadores de errores extremadamente específicos que difieren según si obtengo un valor de un valor de retorno de funciones o si obtengo un valor del índice de una matriz que puede no existir.

¿Hay una captura de prueba simple en Swift como cualquier otro lenguaje de progtwigción popular?

Como se sugiere en los comentarios y otras respuestas, es mejor evitar este tipo de situaciones. Sin embargo, en algunos casos, es posible que desee comprobar si un elemento existe en una matriz y si lo devuelve con seguridad. Para esto puede usar la extensión Array a continuación para devolver de manera segura un elemento de matriz.

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 } } 
  • De esta forma, nunca tocará Index out of range
  • Deberá verificar si el artículo es nil

refiera esta pregunta para más


Probar el código Swift3 en un patio de recreo en Xcode 8.3.2 todavía conduce a un “crash” cuando dejo ar = [1,3,4], y luego v = ar [5]. ¿Por qué? – Thomas Tempelmann, 17 de mayo a las 17:40

Tienes que usar nuestro subíndice personalizado así que en lugar de let v = ar[5] , se let v = ar[safe: 5] .

Valor de obtención predeterminado de la matriz.

 let boo = foo[index] 

Agregar use el subíndice personalizado.

 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 } 

El manejo de errores de Swift ( do / try / catch ) no es la solución para excepciones de tiempo de ejecución como “índice fuera de rango”.

Una excepción de tiempo de ejecución (también puede ver estas trampas llamadas, error fatal , falla de afirmación , etc.) es un signo de error del progtwigdor. Excepto en -Ounchecked comstackciones -Ounchecked , Swift generalmente garantiza que bloquearán su progtwig, en lugar de continuar ejecutando en un estado incorrecto o indefinido. ¡Este tipo de lockings pueden surgir al desencajar con la fuerza ! , desempaquetado implícito, mal uso de referencias unowned , operaciones enteras / conversiones que se desbordan, fatalError() sy precondition() sy assert() s, etc. (Y, por desgracia, excepciones de Objective-C).

La solución es simplemente evitar estas situaciones . En tu caso, verifica los límites de la matriz:

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

(O, como dice el padre en los comentarios, ¡investigue por qué está ocurriendo este problema! Realmente no debería suceder).

Puedes probar un enfoque diferente para esto. ¡Seguramente funcionará!

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

Swift 4:

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

Uso :

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

o

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