Introducción a los valores opcionales de swift 4

¡Acostúmbrate a escribir juntos! Este es el día 19 de mi participación en el "Nuevo plan diario de Nuggets · Desafío de actualización de abril", haga clic para ver los detalles del evento .

Igualdad de valor opcional
 let regex = "123"
 if regex.first == "1" {}
复制代码

El código anterior se puede ejecutar en función de dos puntos, el tipo Wrapped implementa el protocolo Equatable y el Optional implementará el protocolo Equatable

extension Optional: Equatable where Wrapped: Equatable {
    static func ==(lhs: Wrapped?, rhs: Wrapped?) -> Bool {
        switch (lhs, rhs) {
        case (nil, nil): return true
        case let(x?, y?): return x == y
        case (nil, _?), (_?, nil): return false
        }
    }
}
复制代码

No necesariamente necesitamos escribir código como este

if regex.first == Optional("1") {}
复制代码

Cuando usamos un valor no opcional, si necesitamos hacerlo coincidir con un tipo de valor opcional, Swift siempre lo "actualizará" a un tipo de valor opcional

Sin esta conversión implícita, debe implementar tres versiones separadas

// 两者都可选
func == <T: Equatable>(lhs: T?, rhs: T?) -> Bool
// lhs 非可选
func == <T: Equatable>(lhs: T, rhs: T?) -> Bool
// rhs 非可选
func == <T: Equatable>(lhs: T?, rhs: T) -> Bool
复制代码

En realidad, solo necesitamos la primera versión. Muchas veces confiamos en esta conversión implícita, como mapa opcional, convertimos el valor interno y lo devolvemos. Sin embargo, el valor de retorno de nuestro mapa es en realidad un valor opcional, y el compilador completa automáticamente la conversión por nosotros, no necesitamos escribir código como return Optional(transform(value)). En el diccionario, debido a que la clave puede no existir, el valor devuelto es un valor opcional. Si no hay una conversión implícita, debemos escribir el código myDict["key"] = Optional(someValue)

Si desea asignar un valor de cero al diccionario

var dictWithNils: [String: Int?] = ["one": 1,
                                    "two": 2,
                                    "three": nil]
复制代码

dictWithNils["two"] = nil eliminará la clave

Se puede hacer lo siguiente

dictWithNils["two"] = .some(nil)
dictWithNils["two"] = Optional(nil)
dictWithNils["two"]? = nil
复制代码

El tercer método utiliza el método de cadena opcional para establecer el valor después de una adquisición exitosa

No se actualiza ni se inserta ningún valor para valores inexistentes

dictWithNils["four"]? = nil
print(dictWithNils)  // ["one": Optional(1), "two": Optional(2), "three": nil]
复制代码

Cuándo forzar el desempaque

Use un signo de exclamación cuando esté seguro de que un valor no puede ser nulo, ¡debería esperar que si lo es!, el programa simplemente debería colgarse

extension Sequence {
    func alt_commpactMap<T>(_ transform: (Element) -> T?) -> [T] {
        return lazy.map(transform).filter { $0 != nil }.map { $0! }
    }
}
复制代码

Aquí el filtro ha filtrado cero, ¡así que se usa el mapa! No hay ningún problema en absoluto

Mejora el mensaje de error para el desempaquetado forzado
infix operator !!
func !!<T>(wrapped: T?, failtureText:@autoclosure () -> String) -> T {
    if let x = wrapped { return x }
    fatalError(failtureText())
}
复制代码
let s = "foo"
let i = Int(s) !! "Expecting integer, got"(s)""
复制代码
Usar aserciones en compilaciones de depuración

Use la afirmación al hacer afirmaciones, la versión de lanzamiento se reemplazará con el valor predeterminado

infix operator !?
func !?<T: ExpressibleByNilLiteral>(wrapped: T?, failureText: @autoclosure () -> String) -> T {
    assert(wrapped != nil, failureText())
    return wrapped ?? 0 
}
复制代码

Si necesita proporcionar un valor predeterminado explícito, puede definir un parámetro que acepte una tupla que contenga el valor predeterminado y el mensaje de error.

infix operator !?
func !?<T: ExpressibleByNilLiteral>(wrapped: T?, nilDefault: @autoclosure () -> (value: T, text: String)) -> T {
    assert(wrapped != nil, nilDefault().text)
    return wrapped ?? nilDefault().value
}
复制代码
// 调试版本中断言,发布版本中返回 5
Int(s) !? (5, "Expected integer")
复制代码

Para una función que devuelve Void, llamar con encadenamiento opcional devuelve Void? , se puede escribir una versión no genérica para detectar cuándo una llamada de encadenamiento opcional encuentra una operación nula y ninguna.

infix operator !?
func !?(wrapped: ()?, failureText: @autoclosure () -> String) {
    assert(wrapped != nil, failureText())
}
复制代码
var output: String? = nil
output?.write("something") !? "wasn't expecting chained nil here"
复制代码

Supongo que te gusta

Origin juejin.im/post/7088957710860353573
Recomendado
Clasificación