Swift 5.2 - quoi de neuf?

La première version bêta de Swift 5.2 vient d'apparaître dans la version bêta de Xcode 11.4, et il y a eu des changements dans la langue, ainsi qu'une réduction de la taille du code et de la mémoire utilisée, ainsi qu'un nouveau système de diagnostic qui vous permettra de détecter rapidement les erreurs.

Utilisation d'expressions KeyPath comme fonctions


Nous définissons la structure suivante:

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

    var canVote: Bool {
        age >= 18
    }
}

Créons quelques instances de notre structure et mettons-les dans un tableau:

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]

Maintenant attention: si vous avez besoin d'obtenir un tableau de noms de tous les utilisateurs, vous pouvez le faire comme suit:

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

Auparavant, nous devions utiliser une fermeture:

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

De la même manière nouvelle, vous pouvez obtenir tous les utilisateurs qui peuvent voter:

let voters = users.filter(\.canVote)

Et ici, nous recevons tous ceux qui ont un meilleur ami:

let bestFriends = users.compactMap(\.bestFriend)

Valeurs pour les types définis par l'utilisateur


Créez une structure Dice avec les propriétés lowerBound et upperBound, puis ajoutez la fonction callAsFunction . Ainsi, chaque fois que nous obtenons la valeur des dés, nous obtiendrons une valeur aléatoire:

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)

Ici, nous obtenons un nombre aléatoire de 1 à 6, ce qui est complètement identique à un appel direct à callAsFunction (). On pourrait faire la même chose comme ça:

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

Swift sélectionne automatiquement l'appel correct en fonction de la définition de callAsFunction (). Par exemple, vous pouvez ajouter plusieurs paramètres, modifier la valeur de retour et même, si nécessaire, marquer la méthode comme étant en mutation.

Ici, nous allons créer une structure StepCounter qui capture le nombre d'étapes franchies et signale si le nombre d'étapes terminées a atteint 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 () prend également en charge les lancers et les renvois, et vous pouvez définir plusieurs méthodes callAsFunction (), comme avec une surcharge régulière.

L'indice peut déclarer des arguments par défaut


Lorsque vous ajoutez des indices à un type, vous pouvez utiliser les arguments par défaut. Par exemple, si nous avons une structure PoliceForce avec un indice personnalisé pour répertorier les officiers de l'unité, nous pouvons ajouter un paramètre par défaut pour le renvoyer si le tableau est lu en dehors de ses frontières:

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])

Ici, nous obtenons «Amy» puis «Unknown» dans la sortie, car nous n'avons pas d'élément de tableau avec l'index 5.

Puisque nous avons écrit la valeur par défaut par défaut, nous pouvons définir une valeur personnalisée, comme:

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

Diagnostics nouveaux et améliorés


Swift 5.2 introduit une nouvelle architecture de diagnostic dont le but est d'améliorer la qualité et la précision des messages d'erreur de développement Xcode. Cela est particulièrement visible lorsque vous travaillez avec du code SwiftUI, où Swift génère souvent de faux messages d'erreur positifs.

Par exemple, considérez le code suivant:

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)
        }
    }
}

Ici, nous essayons d'associer la vue TextField à un entier Etatpropriété qui ne va pas. Dans ce cas, Swift 5.1 générera une erreur pour le modificateur frame () 'Int' n'est pas convertible en 'CGFloat?' mais Swift 5.2 et versions ultérieures reconnaissent correctement l'erreur dans la liaison de $ name: impossible de convertir la valeur de type 'Binding' en type d'argument attendu 'Binding'.

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


All Articles