Оценка того, является ли ошибка NSError, всегда успешна при преобразовании ошибки, поскольку NSError выдает ошибку компилятора

У нас возникла проблема с объектом Error, который вылетает в коде Crashlytics Objective-c, потому что он не отвечает на userInfo (член NSError), во время исследования я наткнулся на это странное поведение в Swift.

На детской площадке я попытался создать класс SwiftError, реализующий протокол Error:

class SwiftError: Error {
}

let sError = SwiftError()

if sError is NSError { // Generates a warning: 'is' test is always true
    print("Success")
} else {
    print("Fail")
}
// Prints Fail

let nsError = sError as NSError
//Compiler Error: 'SwiftError' is not convertible to 'NSError'; did you mean to use 'as!' to force downcast?
  • Проверка того, является ли SwiftError NSError, дает предупреждение о том, что он всегда успешен, но не работает во время выполнения.
  • Приведение SwiftError как NSError приводит к ошибке компилятора.

Может ли кто-нибудь помочь мне объяснить, почему это происходит и как я могу узнать, действительно ли класс, реализующий протокол Error, является NSError или нет?

Спасибо!


person Mariam K.    schedule 08.03.2021    source источник
comment
Не публикуйте снимки экрана, разместите свой код   -  person Leo Dabus    schedule 08.03.2021
comment
вы можете условно привести свой объект ошибки as? NSError   -  person Leo Dabus    schedule 08.03.2021
comment
Кстати, зачем вам перекидывать Error на NSError? Если вы покажете свою актуальную проблему, мы можем предложить лучшую альтернативу   -  person Leo Dabus    schedule 08.03.2021
comment
Вероятный дубликат stackoverflow.com/questions/41189606/ - мне, наверное, не следовало отвечать.   -  person matt    schedule 08.03.2021
comment
Мне это кажется ошибкой. Приведение sError as NSError завершается ошибкой, только если sError является экземпляром класса, вместо этого он компилируется со структурой или перечислением. И даже с классом let nsError = sError as Error as NSError компилируется.   -  person Martin R    schedule 08.03.2021
comment
На самом деле я не пытался разыграть Error as NSError прямо противоположное, я пытался выяснить, действительно ли Error был NSError, когда он показал мне предупреждение о том, что он всегда успешен. Это подтолкнуло меня к тому, чтобы углубиться в это поведение на детской площадке. То, что я увидел, не имело для меня смысла, поэтому я разместил этот вопрос. @matt @leo   -  person Mariam K.    schedule 12.03.2021


Ответы (2)


Есть что-то странное в природе моста между NSError и Error. Они соединены мостом для целей связи - то есть они могут перемещаться между Swift и Cocoa; и ошибка, которая исходит от Какао является NSError (и NSError принимает протокол ошибок в Swift, чтобы разрешить это); но ваш class, который вы объявляете соответствующим Error, сам по себе не является NSError.

потому что он не отвечает на userInfo

Если вам нужен тип Swift Error для передачи userInfo информации в интересах Какао, то вы искали протокол CustomNSError.

https://developer.apple.com/documentation/foundation/customnserror.

person matt    schedule 08.03.2021
comment
Интересно, что let nsError = sError as NSError компилируется, если sError является экземпляром struct SwiftError: Error или enum SwiftError: Error - он не компилируется только с class SwiftError: Error - person Martin R; 08.03.2021
comment
@MartinR Я предполагаю, что это похоже на Hashable: Swift может вводить соответствие в перечисление или структуру, но не в класс. На самом деле я тоже подумывал прокомментировать это в своем ответе ... - person matt; 08.03.2021
comment
Но let nsError = sError as Error as NSError компилируется и работает. Мне это кажется ошибкой, но я могу ошибаться. Поэтому я решил спросить экспертов: forum.swift.org/t/ - person Martin R; 08.03.2021