2016-01-06 5 views
14

Я столкнулся с этим глупым поведением в быстром темпе, где разворачивание силы необязательно не распространяется.исключение быстрой форматирования без распространения

Из документации:

Попытка использовать! для доступа к несуществующему необязательному значению запускается ошибка времени выполнения. Всегда проверяйте, чтобы опциональное значение содержало ненулевое значение перед использованием! чтобы развернуть ее ценность.

Для воспроизведения:

func foo(bar:String?) throws{ 
    print(bar!); 
} 

И

try foo(nil); 

Это не кажется логичным и последовательным мне, и я не могу найти никакой документации по этому вопросу.

Это по дизайну?

+2

Я не уверен, что ошибка при вызове 'throw' (что является причиной того, что ошибки распространяются из-за такой функции) - это то же самое, что происходит, когда вы принудительно разворачиваете' nil'. Кажется, я где-то читал, что он реализован как 'assert()'. –

+0

Это объяснило бы это, но это ужасно. Возможно, для этого есть аргумент, но на языке, который поддерживает исключения, он просто кажется непоследовательным. – Greg

+7

@ Грег: Николя прав. Обратите внимание, что try/catch обрабатывает Swift * errors * (значения, соответствующие «ErrorType», которые выбрасываются). Это * полностью не связано * с ошибками или исключениями времени выполнения. (В документации даже не упоминается слово «исключение» в связи с throw/try/catch, только «Обработка ошибок».) –

ответ

10

От documentation:

Обработка ошибок

Обработки ошибок является процессом реагирования и восстановления от условий ошибок в программе. Swift предоставляет первоклассную поддержку для метания, ловушки, размножения и управления восстанавливаемыми ошибками во время выполнения.

...

Представляющие и бросание Ошибки

В Swift, ошибки представлены значениями типов, которые соответствуют протокола ErrorType. Этот пустой протокол указывает, что тип может использовать для обработки ошибок.

(Примечание: ErrorType был переименован в Error в Swift 3)

Так с try/catch вы справляетесь Swift ошибки (значения типов, которые соответствуют протоколу ErrorType), которые throw н. Это полностью не связано с ошибками времени выполнения и исключениями времени выполнения (а также не связано с NSException из библиотеки Foundation).

Обратите внимание, что Swift документация по обработке ошибок, даже не использовать слово «исключение», с единственным исключением в (курсив мой) в (!):

ПРИМЕЧАНИЕ обработки

Ошибка в Swift напоминает обработку исключений в других языках , используя ключевые слова try, catch and throw.В отличие от обработка исключений на многих языках, в том числе Objective-C-error Обработка в Swift не включает в себя разворачивание стека вызовов, процесс , который может быть дорого вычислительным. Как таковые, характеристики характеристик оператора throw сопоставимы характеристикам оператора вывода .

разворачивание из которых являются опции nil не throw Свифта ошибки (который может быть размножен) и не может быть обработан с try.

Вы должны использовать хорошо известные методы, как опционального связывания, опционального сцепление, проверку против nil и т.д.

+0

Я никогда не пытался использовать попытку поймать разворачивание, я только говорю о том, что они распространяются. Но вы отвечаете на это просто отлично. Одна из моих возможностей, с которыми я столкнулась, это использование SwiftyJSON и анализ json. У меня есть Entity, который содержит дочерний Entity, который просто бросает (распространяет) несуществующее поле в ответ json. Теперь я использую необязательные инициализаторы для достижения того же, но теперь есть еще 3 строки кода: P – Greg

+0

@Greg: Ну, любая брошенная ошибка должна быть уловлена ​​где-то. Но я изменил формулировку, чтобы лучше ответить на ваш вопрос. –

5

это «сами за себя» пример может помочь вам, чтобы увидеть разницу между поднимая исключение времени выполнения и метание ошибка E, соответствующая протоколу ErrorType.

struct E: ErrorType{} 
func foo(bar:String?) throws { 
    if let error = bar where error == "error" { 
      throw E() 
    } 
    print(bar, "is valid parameter, but don't try to access bar.characters, it crash your code! (if bar == nil)") 
    // here is everything OK 
    let bar = bar! 
    // but here it crash!! 
    _ = bar.characters 
} 

do { 
    try foo("error") 
    // next line is not accessible here ... 
    try foo(nil) 
} catch { 
    print("\"error\" as parameter of foo() throws an ERROR!") 
} 
do { 
    try foo(nil) // fatal error: unexpectedly found nil while unwrapping an Optional value 
} catch { 

} 

печатает

"error" as parameter of foo() throws an ERROR! 
nil is valid parameter, but don't try to access bar.characters, it crash your code! (if bar == nil) 
fatal error: unexpectedly found nil while unwrapping an Optional value 

повышение исключение во время выполнения является фатальной ошибкой в ​​коде.

Смежные вопросы