2016-01-30 2 views
0

Согласно Apple, Swift документации отложитьЯвляется ли «дефер» гарантированным называться в Swift?

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

documentation

Но этот код:

enum SomeError: ErrorType { 
    case BadLuck 
} 

func unluckey() throws { 
    print("\n\tunluckey() -> someone will have a bad day ;)\n") 
    throw SomeError.BadLuck 
} 

func callsUnluckey() throws { 

    print("callsUnluckey() -> OPENING something") 
    defer { 
     print("callsUnluckey() -> CLOSEING something") 
    } 

    print("callsUnluckey() -> WORKING with something") 

    try unluckey() 
    print("callsUnluckey() -> will never get here so chill...") 

    defer { 
     print("callsUnluckey() -> why this is not getting called?") 
    } 
} 

do { 
    try callsUnluckey() 
} catch { 
    print("") 
    print("someone had a bad day") 
} 

Производит этот результат в консоли:

callsUnluckey() -> OPENING something 
callsUnluckey() -> WORKING with something 

    unluckey() -> someone will have a bad day ;) 

callsUnluckey() -> CLOSEING something 

someone had a bad day 

И мой вопрос: почему последний Перенести в callsUnluckey() не называется?.

+0

Программа должна на самом деле дозвониться до отложенного вызова для внутреннего блока, чтобы запланировать его. – dan

+0

Можете ли вы указать мне любую документацию об этом? :) Или любая информация о том, как эти блоки планируются? – sloik

+1

Я сомневаюсь, что это будет документировано, вот как работают программы. – dan

ответ

1

Взгляните на грамматике языка, как представлено в The Swift Programming Language: defer является заявление. В грамматике утверждение является обязательным кодом, который должен выполняться по порядку (в отличие от определения программного элемента, такого как класс или функция, который впоследствии будет использоваться в императивном коде).

Обратите внимание, что бит сразу после части, которую вы указали, зависит от порядка. Если defer был просто объявлением, как функция или свойство или объявление типа, эффект упорядочения не может быть. (Не имеет значения, в каком порядке вы, например, помещаете объявления функций.)

IIRC (на мобильном телефоне прямо сейчас не может быть легко проверено), компилятор поймает вас, если вы положите defer после return, отметив, что это код, который никогда не будет выполнен.

Помните, что «бросание» в Swift под капотом действительно представляет собой особый тип возвращаемого типа. Так что если ваша функция throw s, то код после throw не будет выполнен (и, следовательно, инструкция defer будет иметь возможность создать блок кода, который будет выполнен позднее). Когда вы объявляете функцию throws, любой вызов в ней другой функции бросания становится возможной операцией throw, которая сама по себе является возвратом.

+0

То, как я понимаю ваш ответ, заключается в том, что когда unluckey() бросает это как «возврат» для вызововUnluckey(). В доке говорится -> «Операторы в инструкции defer выполняются независимо от того, как передается управление программой». То, как я вижу это, когда объем вызововUnluckey() заканчивается, он должен назвать последний «defer». Но это не вызвано, и я не понимаю, почему :) (https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Statements.html # // apple_ref/swift/grammar/defer-statement) – sloik

+0

Обратите внимание также, что компилятор будет отмечать отсрочку после оператора возврата как код, который никогда не будет выполнен :) Можете ли вы указать мне место, где я могу проверить, как «откладывается»? : D – sloik

+1

Док, вероятно, должен сказать что-то более похожее: «* после появления заявления о задержке *, инструкции внутри выполняются независимо от того, как после этого будет передаваться управление программой». – rickster

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