Swift 5.2: ¿qué hay de nuevo?

La primera versión beta de Swift 5.2 acaba de aparecer en Xcode 11.4 beta, y ha habido cambios en el idioma, junto con una reducción en el tamaño del código y la memoria utilizada, así como un nuevo sistema de diagnóstico que le permitirá detectar rápidamente los errores.

Usar expresiones de KeyPath como funciones


Definimos la siguiente estructura:

struct User {
    let name: String
    let age: Int
    let bestFriend: String?

    var canVote: Bool {
        age >= 18
    }
}

Vamos a crear algunas instancias de nuestra estructura y ponerlas en una matriz:

let eric = User(name: "Eric Effiong", age: 18, bestFriend: "Otis Milburn")
let maeve = User(name: "Maeve Wiley", age: 19, bestFriend: nil)
let otis = User(name: "Otis Milburn", age: 17, bestFriend: "Eric Effiong")
let users = [eric, maeve, otis]

Ahora atención: si necesita obtener una variedad de nombres de todos los usuarios, puede hacerlo de la siguiente manera:

let userNames = users.map(\.name)
print(userNames)

Anteriormente, necesitábamos usar un cierre:

let oldUserNames = users.map { $0.name }

De la misma forma nueva, puede obtener todos los usuarios que pueden votar:

let voters = users.filter(\.canVote)

Y aquí tenemos a todos los que tienen un mejor amigo:

let bestFriends = users.compactMap(\.bestFriend)

Valores para tipos definidos por el usuario


Cree una estructura Dice con las propiedades lowerBound y upperBound, y luego agregue la función callAsFunction . Por lo tanto, cada vez que obtengamos el valor de los dados, obtendremos un valor aleatorio:

struct Dice {
    var lowerBound: Int
    var upperBound: Int

    func callAsFunction() -> Int {
        (lowerBound...upperBound).randomElement()!
    }
}

let d6 = Dice(lowerBound: 1, upperBound: 6)
let roll1 = d6()
print(roll1)

Aquí obtenemos un número aleatorio del 1 al 6, y esto es completamente idéntico a una llamada directa a callAsFunction (). Podríamos hacer lo mismo así:

let d12 = Dice(lowerBound: 1, upperBound: 12)
let roll2 = d12.callAsFunction()
print(roll2)

Swift selecciona automáticamente la llamada correcta en función de cómo se define callAsFunction (). Por ejemplo, puede agregar varios parámetros, cambiar el valor de retorno e incluso, si es necesario, marcar el método como mutante.

Aquí crearemos una estructura StepCounter que captura el número de pasos dados y señala si el número de pasos completados ha llegado a 10,000:

struct StepCounter {
    var steps = 0

    mutating func callAsFunction(count: Int) -> Bool {
        steps += count
        print(steps)
        return steps > 10_000
    }
}

var steps = StepCounter()
let targetReached = steps(count: 10)

callAsFunction () también admite lanzamientos y repeticiones, y puede definir varios métodos callAsFunction (), como ocurre con la sobrecarga regular.

El subíndice puede declarar argumentos predeterminados


Al agregar subíndices a un tipo, puede usar los argumentos predeterminados. Por ejemplo, si tenemos una estructura PoliceForce con un subíndice personalizado para enumerar los oficiales en la unidad, podemos agregar un parámetro predeterminado para devolverlo si la matriz se lee fuera de sus límites:

struct PoliceForce {
    var officers: [String]

    subscript(index: Int, default default: String = "Unknown") -> String {
        if index >= 0 && index < officers.count {
            return officers[index]
        } else {
            return `default`
        }
    }
}

let force = PoliceForce(officers: ["Amy", "Jake", "Rosa", "Terry"])
print(force[0])
print(force[5])

Aquí obtenemos "Amy" y luego "Desconocido" en la salida, ya que no tenemos un elemento de matriz con el índice 5.

Como escribimos el valor predeterminado predeterminado, podemos establecer un valor personalizado, como:

print(force[-1, default: "The Vulture"])

Diagnósticos nuevos y mejorados


Swift 5.2 presenta una nueva arquitectura de diagnóstico cuyo objetivo es mejorar la calidad y precisión de los mensajes de error de desarrollo de Xcode. Esto es especialmente notable cuando se trabaja con el código SwiftUI, donde Swift a menudo genera mensajes de error falsos positivos.

Por ejemplo, considere el siguiente código:

struct ContentView: View {
    @State private var name = 0

    var body: some View {
        VStack {
            Text("What is your name?")
            TextField("Name", text: $name)
                .frame(maxWidth: 300)
        }
    }
}

Aquí estamos tratando de asociar view TextField con un número entero Estadopropiedad que está mal. En este caso, Swift 5.1 generará un error para el modificador frame () 'Int' no es convertible a 'CGFloat?' , pero Swift 5.2 y posteriores reconocen correctamente el error en el enlace de $ name: no se puede convertir el valor del tipo 'Binding' al tipo de argumento esperado 'Binding'.

Source: https://habr.com/ru/post/undefined/


All Articles