Неустранимая ошибка: индекс конца диапазона не имеет допустимого преемника

Итак, у меня есть проблема с использованием оператора Switch, когда я использовал его с диапазоном, я получаю эту «Фатальную ошибку: индекс конца диапазона не имеет действительного преемника» в консоли.

var ArrayBytes : [UInt8] = [48 ,48 ,48]
 var SuperArrayMensaje : Array = [[UInt8]]()
var num7BM : Array = [UInt8]()

    for var Cont27 = 0; Cont27 < 800; Cont27++ {

        ArrayBytesReservaSrt = String(Mensaje7BM[Cont27])

        switch Mensaje7BM[Cont27] {

        case 0...9 :
                     num7BM = Array(ArrayBytesReservaSrt.utf8)
                     ArrayBytes.insert(num7BM[0], atIndex: 2)

        case 10...99 :
                     num7BM = Array(ArrayBytesReservaSrt.utf8)
                     ArrayBytes.insert(num7BM[0], atIndex: 1)
                     ArrayBytes.insert(num7BM[1], atIndex: 2)

        case 100...255 : // --> THE problem is here "EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)"
                     num7BM = Array(ArrayBytesReservaSrt.utf8) 
                     ArrayBytes.insert(num7BM[0], atIndex: 0)
                     ArrayBytes.insert(num7BM[1], atIndex: 1)
                     ArrayBytes.insert(num7BM[2], atIndex: 2)


        default : break

        }

    SuperArrayMensaje.insert(ArrayBytes, atIndex: Cont27)

                ArrayBytes = [48 ,48 ,48]
    }

person Sebastian Castro    schedule 30.03.2016    source источник
comment
Можете дать информацию о Mensaje7BM?   -  person vien vu    schedule 30.03.2016
comment
Это на самом деле не нужно. Включаемый тип - UInt8.   -  person nhgrif    schedule 30.03.2016
comment
Связано: Меньше или больше, чем в инструкции Swift switch   -  person nhgrif    schedule 30.03.2016


Ответы (1)


Проблему можно воспроизвести с помощью этого MCVE:

let u = 255 as UInt8

switch u {
case 0...9: print("one")
case 10...99: print("two")
case 100...255: print("three")
}

И в некоторой степени мы видим проблему, если просто попытаемся создать переменную диапазона, которая охватила бы этот диапазон:

let r = Range<UInt8>(start: 100, end: 256)

Это не компилируется. Во-первых, мы должны отметить, что аргумент end для конструктора Range не включен в диапазон.

Диапазон 100...255 эквивалентен 100..<256. Если мы попытаемся построить этот диапазон, мы получим ошибку компиляции:

Целочисленный литерал «256» переполняется при сохранении в «UInt8»

Мы не можем создать диапазон, который включает максимальное значение для этого целочисленного типа. Проблема заключается в том, что нет значения UInt8 больше, чем 255. Это необходимо, потому что для того, чтобы что-то содержалось в диапазоне, оно должно быть меньше, чем значение диапазона end. То есть он должен возвращать true при сравнении с оператором <. И нет значения UInt8, которое могло бы заставить это утверждение: 255 < n вернуть истину. Следовательно, 255 никогда не может находиться в диапазоне типа UInt8.

Значит, надо найти другой подход.

Как программист, мы можем знать, что диапазон, который мы пытаемся создать, представляющий все трехзначные десятичные числа, которые вписываются в UInt8, мы могли бы просто использовать здесь случай default:

let u = 255 as UInt8

switch u {
case 0...9: print("one")
case 10...99: print("two")
default: print("three")
}

Это кажется самым простым решением. Мне больше всего нравится этот вариант, потому что мы не получаем дело default, которое, как мы знаем, никогда не будет выполнено.

Если мы действительно явно хотим, чтобы кейс охватывал все значения от 100 до UInt8 max, мы также можем сделать это:

switch u {
case 0...9: print("one")
case 10...99: print("two")
case 100..<255, 255: print("three")
default: print("how did we end up here?")
}

Или вот так:

switch u {
case 0...9: print("one")
case 10...99: print("two")
case 100...255 as ClosedInterval: print("three")
default: print("default")
}

Дополнительные сведения о ClosedInterval см. в документации Apple или документ Swift.

person nhgrif    schedule 30.03.2016