NSError и Ошибка в Swift - PullRequest
       40

NSError и Ошибка в Swift

0 голосов
/ 24 апреля 2018

Я видел, что уже есть вопрос о разнице между NSError и Error в Swift, и я знаю о различиях.Тем не менее, я не понимаю поведение фрагмента кода ниже, так как он компилируется правильно.Механизм обработки ошибок Swift требует, чтобы каждый блок do-catch не появлялся в функции с предложением throws, чтобы включить один универсальный обработчик (либо catch без каких-либо других данных, либо catch для Error).Однако, похоже, что использование NSError имеет тот же эффект.Кто-нибудь здесь знает причину?Я прочитал в другой вопрос , что «любой класс, соответствующий ErrorType, может быть приведен к NSError. Эти функции описаны здесь в документации».Тем не менее, документация , на которую указывает этот ответ, не прояснила мне этот момент, так как она сосредоточена на Objective-C, который я не использую.

import Foundation
extension Int : Error {}
extension String : Error {}

func fErr() throws {
  let a = Int(readLine()!)!
  if a > 20 {
    throw 42
  } else {
    throw "An error occurred"
  }
}

func gErr() {
  do {
    try fErr()
  } catch let e as NSError {
    print(e)
  }
}

Ответы [ 2 ]

0 голосов
/ 25 апреля 2018

На платформах Дарвина (macOS, iOS, tvOS, watchOS) Swift имеет концепцию под названием bridging , которая позволяет типам Swift, предлагаемым стандартной библиотекой, связывать с типами Objective-C (обычно обдуваемый каркасом Какао). Типы, которые делают это, включают

  • Array ↔︎ NSArray
  • Dictionary ↔︎ NSDictionary
  • Set ↔︎ NSSet
  • Error ↔︎ NSError
  • и т.д.. (см. ссылку выше для более полного списка)

Для типов мостов требуется поддержка компилятора, а мост Error ↔︎ NSError имеет вполне несколько компонентов ( среди прочих * 1036) *). Этот мост, тем не менее, позволяет компилятору обрабатывать NSError s как Error s и наоборот; фактически, как вы можете видеть из приведенного выше фрагмента, любой Error может быть приведен к NSError и обратно.

Вы можете увидеть некоторые компоненты времени выполнения, необходимые для того, чтобы это произошло, в другом моем ответе на пользовательском NSError s , но суть в том, что любой Error может предоставить достаточно информации для переноса в экземпляре NSError (путем реализации var _domain, var _code и var _userInfo) и наоборот.

Когда вы ловите ошибку as NSError, вы неявно соединяете Error (независимо от того, что это) в NSError, так же, как вы можете соединить [1, 2, 3] as NSArray или ["foo" : "bar"] as NSDictionary.

[Обратите внимание, что мостовое соединение в настоящее время доступно только там, где доступна среда выполнения Objective-C, то есть только на платформах Darwin. Такие мостовые вызовы не работают в Linux.]

См. Также SE-0112 Улучшенное мостовое соединение NSError (оригинальное предложение Swift Evolution) для получения дополнительной информации об этом и более подробной информации.

0 голосов
/ 24 апреля 2018

Как я вижу, где-то неявное преобразование где-то в исходном коде Swift.

Одним из возможных доказательств является эта часть C ++ code Optional<SILDeclRef> ErrorToNSErrorFn;

...