Swift 5.2 - o que há de novo?

A primeira versão beta do Swift 5.2 acaba de aparecer no Xcode 11.4 beta, e houve mudanças no idioma, além de uma redução no tamanho do código e da memória usada, além de um novo sistema de diagnóstico que permitirá uma detecção mais rápida de erros.

Usando expressões KeyPath como funções


Definimos a seguinte estrutura:

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

    var canVote: Bool {
        age >= 18
    }
}

Vamos criar algumas instâncias da nossa estrutura e colocá-las em uma 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]

Agora atenção: se você precisar obter uma matriz de nomes de todos os usuários, poderá fazer o seguinte:

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

Anteriormente, precisávamos usar um fechamento:

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

Da mesma maneira nova, você pode obter todos os usuários que podem votar:

let voters = users.filter(\.canVote)

E aqui temos todos que têm um melhor amigo:

let bestFriends = users.compactMap(\.bestFriend)

Valores para tipos definidos pelo usuário


Crie uma estrutura de dados com as propriedades lowerBound e upperBound e adicione a função callAsFunction . Assim, toda vez que obtivermos o valor dos dados, obteremos um valor aleatório:

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)

Aqui obtemos um número aleatório de 1 a 6, e isso é completamente idêntico a uma chamada direta para callAsFunction (). Poderíamos fazer a mesma coisa assim:

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

Swift seleciona automaticamente a chamada correta com base em como callAsFunction () é definido. Por exemplo, você pode adicionar vários parâmetros, alterar o valor de retorno e até, se necessário, marcar o método como mutante.

Aqui, criaremos uma estrutura StepCounter que captura o número de etapas executadas e sinaliza se o número de etapas concluídas atingiu 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 () também suporta lançamentos e repetições, e você pode definir vários métodos callAsFunction (), como ocorre com sobrecarga regular.

O subscrito pode declarar argumentos padrão


Ao adicionar subscritos a um tipo, você pode usar os argumentos padrão. Por exemplo, se tivermos uma estrutura PoliceForce com um subscrito personalizado para listar oficiais na unidade, podemos adicionar um parâmetro padrão para retorná-lo se a matriz for lida fora de suas bordas:

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

Aqui obtemos "Amy" e "Desconhecido" na saída, pois não temos um elemento de matriz com o índice 5.

Como escrevemos o padrão padrão, podemos definir um valor personalizado, como:

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

Diagnósticos novos e aprimorados


O Swift 5.2 apresenta uma nova arquitetura de diagnóstico cujo objetivo é melhorar a qualidade e a precisão das mensagens de erro de desenvolvimento do Xcode. Isso é especialmente perceptível ao trabalhar com o código SwiftUI, onde o Swift geralmente gera mensagens de erro positivas falsas.

Por exemplo, considere o seguinte 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)
        }
    }
}

Aqui estamos tentando associar a visualização TextField a um número inteiro Estadopropriedade que está errada. Nesse caso, o Swift 5.1 gerará um erro para o modificador de quadro () 'Int' não ser convertível em 'CGFloat?' mas o Swift 5.2 e posterior reconhecem corretamente o erro na ligação de $ name: Não é possível converter o valor do tipo 'Ligação' no tipo de argumento esperado 'Ligação'.

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


All Articles