Всегда ли необязательная цепочка Swift выполняется с помощью конструкции if let, или это просто вопросительный знак с необязательной?

Согласно документам Apple, необязательные цепочки следующие:

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

Моя интерпретация этого заключается в том, что следующая конструкция является необязательной цепочкой:

someMasterObject.possiblyNilHandler?.handleTheSituation()

... и что приведенная выше строка будет вызывать метод handleTheSituation, если обработчик не равен nil, и завершается неудачно (пропускается строка), если обработчик равен nil.

Тем не менее, почти во всех примерах, которые я вижу о необязательном объединении в цепочку, используется конструкция if if:

if let handler = someMasterObject.possiblyNilHandler{
  handler.handleTheSituation()
}

Фактически, документация и примеры, которые я нашел в сети, настолько интенсивно используют конструкцию "если позволено" в отношении необязательного сцепления, что кажется, что это НЕОБЯЗАТЕЛЬНОЕ сцепление.

Однако правильно ли я, предполагая, что мой первый пример - это поддерживаемое использование необязательной цепочки и что конструкция if let - это другая конструкция, использующая (или тесно связанная с) необязательную цепочку?

3 ответа

Решение

Вывод правильный - let является независимой, но полезной конструкцией. В контексте он вводит привязку только в теле if и выполняет тело if, только если значение привязки не равно nil. (Технически это разворачивает необязательную привязку.)

let не влияет на то, как обрабатывается выражение справа (с цепочкой или без нее). Например, если someMasterObject были необязательны / ноль, он потерпит неудачу, а не "цепочка" - даже с let,

Когда один или другой (или оба) более "правильный", зависит от ситуации: например. что должно быть приковано и какими должны быть корректирующие действия.


Например, если someMasterObject может быть ноль, у нас может быть следующее, которое использует как цепочку и let, Также обратите внимание, как значение возврата имеет значение, а не просто отбрасывается или "ноль при ошибке":

if let handler = someMasterObject?.possiblyNilHandler{
  return handler.handleTheSituation()
} else {
  return FAILED_TO_CALL
}

Затем сравните его с неэквивалентной цепочечной формой, которая вернет только nil в случае неудачного вызова, но nil может быть допустимым возвращаемым значением из handleTheSituation!

return someMasterObject?.possiblyNilHandler?.handleTheSituation()

С другой стороны, учтите, что всегда есть прямой перевод цепочки во вложенные операторы if-let:

result_of_expression = someMasterObject?.possiblyNilHandle?.handleTheSituation()

if let master = someMasterObject {
   if let handler = master.possiblyNilHandler {
       result_of_expression = handler.handleTheSituation()
   } else {
       result_of_expression = nil
   }
} else {
   result_of_expression = nil
}

Необязательное связывание полезно в большем количестве случаев, чем просто необязательное связывание (if let):

person?.name = "Fred"              // assign "Fred" to name property if person is not nil

person?.congratulate()             // call congratulate method if person is not nil

let name = person?.name ?? "none"  // nil coalescing operator

let age = dict?["age"] ?? 0        // subscripting an optional variable

if var name = person?.name {       // optional binding using var instead of let

Вызов методов через опциональную цепочку совершенно нормально - вам не нужно if вокруг него. Если необязательное значение оказывается nil во время вызова ваш код не будет выдавать исключение. Однако вы не сможете узнать, был ли запущен метод или нет.

Тем не менее, как правило, вы хотите разместить if вокруг необязательного вызова метода цепочки, чтобы определить, был ли вызван метод или нет:

func printNumberOfRooms() {
    println("The number of rooms is \(numberOfRooms)")
}

if john.residence?.printNumberOfRooms() != nil {
    println("It was possible to print the number of rooms.")
} else {
    println("It was not possible to print the number of rooms.")
}

Ссылка на главу книги.

Обратите внимание, что nil check работает, хотя функция в примере не имеет возвращаемого значения. Поскольку он вызывается для необязательного значения с использованием необязательного сцепления, тип Void?не Void, что делает сравнение возможным.

Другие вопросы по тегам