ios - uitableviewcell - ¿Cómo atrapo el "Índice fuera de rango" en Swift?
uitableviewcell swift (4)
Realmente me gustaría usar un bloque try 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 TableView se vuelve a cargar con nuevos datos, todavía hay información en la RAM que llama
didEndDisplayingCell
en una tableView con un origen de datos recién vacío para bloquearse.
Así que frecuentemente arrojé 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 muy baja prioridad, y he perdido mucho tiempo con el método de prueba y error para averiguar qué manejador de errores integrado funciona rápidamente para lo que parecen ser situaciones extremadamente únicas cuando tengo toneladas 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 un valor del índice de una matriz que puede no existir.
¿Hay un simple intento de detectar Swift como cualquier otro lenguaje de programación popular?
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 }
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 verificar si un elemento existe en una matriz y si lo devuelve de manera segura. Para esto, puede usar la siguiente extensión de matriz para devolver de forma 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 manera,
nunca alcanzarás el
Index out of range
-
Tendrás que comprobar si el artículo es
nil
consulte esta pregunta para más
Probar el código Swift3 en un área de juegos en Xcode 8.3.2 todavía conduce a un "bloqueo" cuando dejo ar = [1,3,4], luego dejo v = ar [5]. ¿Por qué? - Thomas Tempelmann 17 de mayo a las 17:40
Debe utilizar nuestro subíndice personalizado para que, en lugar de
let v = ar[5]
, se
let v = ar[safe: 5]
.
Valor predeterminado de obtención 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
developer.apple.com/library/ios/documentation/Swift/Conceptual/…
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 estos llamados
trampa
,
error fatal
,
falla de aserción
, etc.) es un signo de error del programador.
Excepto en
-Ounchecked
compilaciones sin
-Ounchecked
, Swift generalmente garantiza que
bloqueará
su programa, en lugar de continuar ejecutándose en un estado incorrecto / indefinido.
¡Este tipo de accidentes pueden surgir de un desenvolvimiento forzado
!
, desenvolvimiento implícito, uso indebido de referencias
unowned
propiedad, operaciones / conversiones de enteros que se desbordan,
fatalError()
sy
precondition()
sy
assert()
s, etc. (Y, desafortunadamente, excepciones de Objective-C).
La solución es simplemente evitar estas situaciones . En su caso, verifique 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 rmaddy en los comentarios, ¡investigue por qué ocurre este problema! Realmente no debería suceder en absoluto).
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)
}
}