Обработка ошибок времени выполнения в Swift

Я полностью осознаю, что Swift не имеет механизма try/catch для обнаружения исключений (OK, Swift 2.0 теперь поддерживает их). Я также понимаю, что многие методы API возвращают NSError, который будет заполнен объектом ошибки, если что-то пойдет не так. Поэтому, пожалуйста, не указывайте мне на этот вопрос: Обработка ошибок в Swift-Language

Но это все еще не объясняет, как реагировать на ошибки времени выполнения в вашем собственном коде, например, получать доступ к массиву вне пределов доступа или принудительно разворачивать необязательное значение, равное нулю. Например:

var test: String?
test = nil
println(test!) //oops!

или

var arr = [0,1,2]
for i = 0...3 {
    println(arr[i]) //oops!
}

Каждый программист иногда делает такие ошибки, и должен быть способ, по крайней мере, записать их для последующего анализа. Во время отладки Xcode может показать нам это, но что, если это произойдет с конечным пользователем или бета-тестером? В чистом C есть обработка сигнала, и ее можно использовать и в Objective-C. В Свифте есть что-то подобное? Централизованный обратный вызов был введен непосредственно перед тем, как приложение умирает?

Update:

Позвольте мне перефразировать вопрос: в большом проекте не удается вручную проверить указанные выше ошибки на каждом цикле и принудительно развернуть. Когда в конечном итоге возникает ошибка времени выполнения, существует ли обратная связь, например, обработка объекта Seegfault Objective C или NSSetUncaughtExceptionHandler, которая будет вызвана так, чтобы ошибка могла быть зарегистрирована/отправлена ​​по электронной почте вместе со стоп-лоском аварии?

Ответы

Ответ 1

Изменить: этот ответ не обновляется с помощью swift 2.0. Так как сейчас у нас есть обработка ошибок, я не обновил ниже ответ. Некоторые аспекты обработки ошибок будут обновлены в будущем с помощью swift 3.0. Вы можете выполнить этот ответ Обработка ошибок в Swift-Language

Swift - typeSafe language.It получить ошибку во время компиляции, а не ждать, чтобы вызвать ее во время выполнения.

В первом примере вы используете Optional.

var test: String?

Сначала понимаем значение Optional. Когда вы указываете Optional, вы говорите, что это может быть nil or have no value. Теперь, когда вы разворачиваете test, вы говорите, что я знаю, что это значение not nil.Пожалуйста, распакуйте его. я уверен в этом. Итак, ваша ответственность за то, чтобы увидеть, где он nil. Если вы не уверены в этом, вы должны использовать необязательное связывание здесь. Когда вы не уверены в значении, всегда используйте if condition while unwrrapping

  if let notNilTest = test {
    //use notNilTest
  }
  else{
   //handle error
  }

Во втором примере должно иметь смысл иметь обработку исключений во время выполнения, но вы можете легко получить это с условием if, имеющим count.So во втором примере в качестве разработчика вы должны использовать условие для получения count массива.

Из быстрого руководства:

Если вы попытаетесь использовать синтаксис индекса для извлечения или установки значения для индекс, который находится за пределами существующих границ массивов, вы будете запускать ошибка времени выполнения. Однако вы можете проверить, что индекс действителен до используя его, сравнивая его со свойством count массива. За исключением случаев, когда count равен 0 (это означает, что массив пуст), самый большой действительный индекс в array всегда будет count - 1, потому что массивы индексируются с нуля.

Они ясно упоминают об этом, и вы должны позаботиться об этих вещах, чтобы сделать ваш код менее багги. Некоторые вещи, которые они предоставили, и мы должны знать о том, как использовать эти вещи.

Ответ 2

Рассмотрите возможность использования инструкции охраны вместо нескольких, если позволяет.

var arr = [0,1,2]
for i = 0...3 {
    Guard arr[i] != nil else {
        Continue
    }
    println(arr[i]) //oops!
}

Или вместо

if let x = some value {
    If let y = someOtherVal {
        If let z = yetanotherVal {
            Product = x * y* z
        }
    }
}

Не так же аккуратно, как:

Let x = someVal
Let y = someOtherVal
Let z = yetAnotherVal

Guard x != nil,
  y != nil,
  z != nil
Else {
  Return
}

Product = x * y * z