2016-10-08 3 views
2

Я использую следующий Swift код, чтобы установить ключевую строку в зависимости от значения единицы измерения:Предупреждение для трехкомпонентной условного оператора происходит только в локальной области

let units = 0 
let key = units == 0 ? "F" : "C" 
// this example makes key = "F" 

Приведенный выше пример работает как и должно быть без каких-либо предупреждений, когда это в глобальном масштабе файла Swift. Тем не менее, когда я помещаю один и тот же код в инициализаторе или в функции, я получаю предупреждение со ссылкой на «C» термин:

struct Almanac { 
    // properties 
} 

extension Almanac { 

    init?(json: [String: Any]) { 
     let units = 0 
     let key = units == 0 ? "F" : "C" // WARNING: Will never be executed 

     // ... 
    } 

} 

func logunits() { 
    let units = 0 
    let key = units == 0 ? "F" : "C" // WARNING: Will never be executed 
    print("key is \(key)") 
} 

Почему это только предупреждение появляется, когда тройная условно используется на местном объем?

+0

Насколько я понимаю, это имеет ничего не связано с неудачными инициализаторами - вы получите то же предупреждение, если просто поместите код в функцию. Это только не дает вам предупреждения, когда он находится на верхнем уровне файла main.swift или игровой площадки (независимо от того, предназначено это или нет, я не могу сказать) – Hamish

+0

@Hamish На основании вашего комментария я пересмотрел свои вопрос. Я все равно хотел бы знать, почему область действия оператора вызывает предупреждение. – wigging

ответ

0

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

С этим:

func logunits() { 
    let units = 0 
    let key = units == 0 ? "F" : "C" 
    print("key is \(key)") 
} 

компилятор имеет units = 0 и units == 0 ? в том же объеме, поэтому она способна решить путь (потому что ничего не изменяет значение units между двумя линиями) и сказать, что да, действительно, единицы равны 0 и да, «C» всегда будет игнорироваться.

Если изменить значение:

func logunits() { 
    let units = 1 
    let key = units == 0 ? "F" : "C" 
    print("key is \(key)") 
} 

предупреждение внезапно выскакивает из "C" до "F". :)

А если поставить значение из сферы:

let units = 0 

func logunits() { 
    let key = units == 0 ? "F" : "C" 
    print("key is \(key)") 
} 

предупреждение исчезает.

Обратите внимание, что если есть какой-либо код в пути, который может изменить значение units, даже глупый, как в этом примере, предупреждение исчезает:

func logunits() { 
    var units = 0 
    if true { units = 1 } 
    let key = units == 0 ? "F" : "C" 
    print("key is \(key)") 
} 
+0

Так это ошибка компилятора в Xcode? – wigging

+0

Так почему он способен проверять ценность в некоторых контекстах, а не в других? – wigging

+0

@ wigging Потому что в некоторых контекстах он может видеть, что ничто не изменит значение, например, когда оно находится в локальной области видимости, а две строки последовательны. Если вы сообщите компилятору «эй, что это значение равно нулю, о, как это значение, поэтому я могу выбрать другое?» он ответит «ну, это нуль, как вы только что сказали линии раньше ...». Если вы вводите что-либо, что может изменить значение, эта функция перестает работать, потому что она работает только в том случае, если контекст является 100% гарантией без мутации для анализируемого значения. Если значение может меняться во время выполнения, эта функция компилятора не применяется. – Moritz