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'.