Как правильно сделать Nil Coalescing в Swift?
Предполагается сделать так
var inputField = UITextField()
let defaultText = "PLACEHOLDER"
let newText = inputField.text!.isEmpty ? defaultText : inputField.text!
let newText2 = inputField.text ?? defaultText
newText
работает и выводит PLACEHOLDER
,
Но newText
только показывает ""
в окне предварительного просмотра в Swift
Зачем? Как сделать это правильно?
2 ответа
Есть большая разница между ""
а также nil
, Ваш text
свойство пустое, но это не nil
, (Это на самом деле равно строке ""
.) Таким образом, ваша проверка .isEmpty
работает, но ваша попытка слиться не сработает. Это, с другой стороны, будет работать:
let text: String? = nil
let newText2 = text ?? defaultText
Итак, ваше понимание слияния ноль в порядке; Ваше предположение, что пустое текстовое поле возвращает nil
is not: фактически возвращает пустую - но существующую - строку.
import UIKit
var inputField = UITextField()
inputField.text?.isEmpty // true !!!
// by deafault it is empty, so i set it
inputField.text = "default text"
let defaultText = "PLACEHOLDER"
let newText = inputField.text?.isEmpty == true ? defaultText : inputField.text!
let newText2 = inputField.text ?? defaultText
print(newText) // default text
print(newText2) // default text
в вашем фрагменте newText2 пустая строка, потому что inputField.text не ноль
безопасный способ, как это сделать (inputField.text может быть ноль, пустой или некоторый текст)
import UIKit
var inputField = UITextField()
let defaultText = "PLACEHOLDER"
if let txt = inputField.text {
inputField.text = txt.isEmpty ? defaultText : txt
}
let newText = inputField.text ?? defaultText
print(inputField.text, newText) // Optional("PLACEHOLDER") PLACEHOLDER
В результате, если inputField.text пуст или равен nil, ему присваивается некоторое значение по умолчанию, в противном случае текст не изменяется
Более быстрое решение для проверки ":x
empty или nil?"- использовать расширение:
extension Optional where Wrapped == String {
var nilIfEmpty: String? {
guard let strongSelf = self else {
return nil
}
return strongSelf.isEmpty ? nil : strongSelf
}
var isEmptyOrNil: Bool {
guard let strongSelf = self else {
return true
}
return strongSelf.isEmpty
}
}
Причина let newText2 = inputField.text ?? defaultText
терпит неудачу потому что inputField.text = ""
по умолчанию, что не попадает в nil
случай оператора nil-coalescing (как Optional("") != nil
).
Вы можете использовать эти Optional<String>
расширения для замены:
let newText = inputField.text!.isEmpty ? defaultText : inputField.text!
let newText2 = inputField.text ?? defaultText
с
let newText = inputField.text.isEmptyOrNil ? defaultText : inputField.text!
let newText2 = inputField.text.nilIfEmpty ?? defaultText
оба работают правильно. Хотя я бы рекомендовал безопасно развернутьinputField.text
вместо использования !
оператор (хотя это технически безопасно, я стараюсь по возможности избегать использования оператора взрыва) - отсюда и решение nil-coalescing, использующее nilIfEmpty
предпочтительнее.
Кроме того, вы можете использовать последнее, чтобы предотвратить распространенное (и беспорядочное) someOptionalString?.isEmpty ?? true
танцевать в операторах if и тернарных операциях, как:
if someOptionalString.isEmptyOrNil {
// Do something when a string is empty or nil...
}
намного чище, чем
if someOptionalString?.isEmpty ?? true {
// Do something when a string is empty or nil...
}