O que há de novo no Swift 5?

Olá, meu nome é Ilya. Sou desenvolvedor iOS do Tinkoff.ru. Neste artigo, darei uma breve visão geral das principais alterações no Swift 5. Essas alterações são descritas nas notas de versão . Para quem ainda não se familiarizou, seja bem-vindo ao gato!



O tamanho do aplicativo diminuirá!


Os aplicativos escritos no Swift 5 e compilados para iOS 12.2, watchOS 5.2, tvOS 12.2 não incluirão bibliotecas dinâmicas para a biblioteca padrão Swift e o Swift SDK. E isso significa que o tamanho do aplicativo diminuirá, no entanto, não muito. Se você acredita neste tweet , o tamanho do projeto vazio foi reduzido de 2,4 Mb para 24 Kb. Um bom resultado para aplicativos pequenos, mas para aplicativos grandes não haverá muita diferença.

@dynamicCallable ( SE-0216 )


O atributo @dynamicCallable permite trabalhar com um objeto como uma função. Esses objetos são chamados de objetos funcionais ou functors (mais detalhes podem ser encontrados aqui ). Os objetos funcionais estão em C ++, Python, JavaScript e outras linguagens, e no Swift eles foram adicionados para compatibilidade com essas linguagens. O fato é que o Swift agora interage bem com a API C e o Objective-C, e os desenvolvedores de idiomas desejam adicionar interação com linguagens dinâmicas - Python, JavaScript, Ruby e outros.

Para tornar um tipo um functor, você deve adicionar o atributo @dynamicCallable à sua declaração. Considere um exemplo de uma estrutura redutora que pode ser usada para adicionar números em uma matriz:

@dynamicCallable struct Reducer { ... } 

Então você precisa implementar um ou ambos dos seguintes métodos:

 func dynamicallyCall(withArguments: ExpressibleByArrayLiteral) func dynamicallyCall(withKeywordArguments: ExpressibleByDictionaryLiteral) 

A primeira função permite acessar o objeto passando uma matriz como argumentos. A segunda função permite acessar o objeto, passando a mesma matriz que os argumentos, mas usando os nomes dos argumentos.

Por exemplo, uma implementação da primeira função para uma estrutura Redutora ficaria assim:

 func dynamicallyCall(withArguments arguments: [Int]) -> Int { return arguments.reduce(0, +) } 

Em seguida, aplique uma estrutura da seguinte maneira:

 let reducer = Reducer() let sum = reducer(1, 2, 3) // sum = 6 

Consideraremos a implementação do segundo método usando o exemplo da estrutura Comparator , com a qual podemos comparar dois números:

 @dynamicCallable struct Comparator { func dynamicallyCall(withKeywordArguments arguments: KeValuePairs<String, Int>) -> ComparisonResult { guard let lhs = arguments["lhs"], let rhs = arguments["rhs"], lhs != rhs else { return .orderedSame } return lhs > rhs ? .orderedDescending : .orderedAscending } } 

Você pode usar essa estrutura da seguinte maneira:

 let comparator = Comparator() let comparisionResult = comparator(lhs: 1, rhs: 2) // comparisionResult = .orderedAscending 

Atributo desconhecido no comutador ( SE-0192 )


Muitas pessoas sabem que ao processar valores de enumeração, é necessário descrever todos os casos e tentar não usar o padrão. Embora esse requisito adicione uma pitada de segurança, ele também tem uma desvantagem, pois ao alterar valores na enumeração, você precisa adicionar o processamento deles. Ainda existe a possibilidade de que a estrutura do sistema altere uma das enumerações, mas isso não foi processado no seu aplicativo (por exemplo, com LABiometryType ).

O Swift 5 adicionará o atributo desconhecido , o que permitirá que você separe 2 cenários diferentes ao processar uma enumeração:

  • O código padrão deve ser executado para todos os casos não processados ​​no switch
  • Todos os casos são processados ​​no switch e, se novos forem adicionados, você precisará usar o código no padrão

Vejamos um exemplo:

 enum HTTPMethod { case post, get, put } //  @unknown switch httpMethod { case .post: print("Post") case .get: print("Get") default: print("Put") } //  @unknown switch httpMethod { case .post: print("Post") case .get: print("Get") @unknown default: print("Unknown HTTP method") } 

Livrar-se de double Opcional como resultado de chamar uma função com try? ( SE-0230 )


Certamente muitos já se depararam com o fato de que, ao chamar a função jogável, que retorna Opcional , usando try? , o resultado é um tipo agrupado em dois Opcional . Isso não é muito conveniente e, portanto, no Swift 5, ligue para tentar? nesse caso, retornará um tipo agrupado em apenas um opcional .

Foi assim que aconteceu antes do Swift 5:

 let result = try? optionalObject?.foo() // type(of: result) = SomeType?? 

E assim será no Swift 5:

 let result = try? optionalObject?.foo() // type(of: result) = SomeType? 

Verificação de multiplicidade ( SE-0225 )


Para verificar a multiplicidade de um número para outro, você pode usar a função isMultiple (of :) , em vez do restante da divisão (%):

 //   let isEven = 4 % 2 == 0 //   let isEvent = 4.isMultiple(of: 2) 

A alteração é pequena, mas torna o código um pouco mais claro e simplifica a pesquisa por código.

Contando o número de elementos em uma sequência com uma condição ( SE-0220 )


No Swift 5, o tipo Sequence adicionará o método count (where: (Element) -> Bool) -> Int , que permitirá contar o número de elementos em uma sequência que satisfazem uma determinada condição em uma passagem. Antes disso, eu tinha que usar o filtro em conjunto com o count . Este método salvará a memória alocada ao criar uma nova matriz no método de filtro .

Um exemplo:

 let countOfZeroes = [0, 1, 2, 0, 4].count(where: { $0 == 0 }) // countOfZeroes = 2 

Método CompactMapValues ​​no dicionário ( SE-0218 )


Este método combina compactMap da matriz e mapValues do dicionário . Como resultado da chamada desse método, um dicionário com valores transformados é criado no qual não há valores iguais a zero .

Um exemplo:

 let dictionary = ["a": "1", "b": "2", "c": "Number"] let resultDictionary = dictionary.compactMapValues { Int($0) } // resultDictionary = ["a": 1, "b": 2] 

Sequências brutas ( SE-0200 )


Foi adicionada a capacidade de escrever linhas nas quais aspas e barras invertidas são usadas como caracteres regulares, e não como caracteres especiais. Para fazer isso, adicione o caractere # no início e no final da linha.

Um exemplo:

 let string1 = #"   " ""# let string2 = #"  \ "# 

Se você estiver inserindo uma variável ao criar uma linha, após a barra invertida, precisará adicionar o sinal #:

 let string = #"   \#(variable)"# 

Se a linha tiver um sinal de #, no início e no final da linha você precisará adicionar dois sinais de ##:

 let string = ##"   #"## 

O protocolo de sequência não contém mais o tipo associado SubSequence ( SE-0234 )


O tipo associativo de SubSequence foi movido do protocolo Sequence para Collection.Agora, todos os métodos em Sequence que retornaram SubSequence retornam um tipo específico. Por exemplo, o método do sufixo agora retorna uma matriz . Aqui está a lista completa dos métodos afetados por essa alteração:

 extension Sequence { public func dropFirst(_ k: Int = 1) -> DropFirstSequence<Self> public func dropLast(_ k: Int = 1) -> [Element] public func suffix(_ maxLength: Int) -> [Element] public func prefix(_ maxLength: Int) -> PrefixSequence<Self> public func drop(while predicate: (Element) throws -> Bool) rethrows -> DropWhileSequence<Self> public func prefix(while predicate: (Element) throws -> Bool) rethrows -> [Element] public func split( maxSplits: Int = Int.max, omittingEmptySubsequences: Bool = true, whereSeparator isSeparator: (Element) throws -> Bool ) rethrows -> [ArraySlice<Element>] } 

Agora, trabalhar com esses métodos ficará mais fácil.

Restrições de protocolo


Os protocolos agora suportam a restrição na forma de classes que implementam esse protocolo. Em outras palavras, agora você pode indicar que um protocolo só pode ser implementado por uma classe específica. Por exemplo:

 protocol Viewable: UIView {} protocol Viewable where Self: UIView {} 

A segunda opção de gravação é suportada no Swift 4.2, mas pode causar um erro de compilação ou tempo de execução. No Swift 5, esse erro não ocorrerá.

Conclusão


Esta não é uma lista completa de alterações no Swift 5; apenas as principais alterações são coletadas aqui. Em geral, as mudanças apresentadas são positivas e tornam a linguagem mais compreensível e flexível. O principal é que “Converter para a sintaxe Swift atual” deve ser indolor.

Isso é tudo, obrigado pela leitura.

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


All Articles