Olá Caio, tudo bom?
Essa estrutura com o T
é a forma de usar classe genérica em Swift.
A assinatura do método load
diz que o retorno desse método é uma classe qualquer, representada por T, que seja filha ou que implemente Decodable. Vejamos:
func load<T: Decodable>(_ filename: String) -> T
O final do método -> T
diz que o retorno é um objeto do tipo da classe T, enquanto a estrutura <T:Decodable>
diz que T é a representação de uma classe genérica filha de Decodable. Em outras palavras, o retorno desse método é qualquer objeto da classe filha de Decodable.
A classe Viagem
é filha de Codable
, ou seja, ela implementa Decodable
e Encodable
(veja a definição de Codable
), logo, ela é uma classe que poderia ser usada no lugar de T. Então quando você diz:
let viagens: [Viagem] = load("viagens.json")
você está declarando uma variável viagens
que é um array de objetos dos tipo Viagem, e eles serão lidos do arquivo viagens.json
usando o método load
, que neste caso, usa a classe genérica T para representar a classe Viagem
que será usada para representar os conjuntos de informações do JSON.
Vou colocar o código com comentários:
import Foundation
let viagens: [Viagem] = load("viagens.json") //declara o array com as viagens
func load<T: Decodable>(_ filename: String) -> T { //assinatura do método com uso de classe genérica
let data: Data
guard let file = Bundle.main.url(forResource: filename, withExtension: nil) //declara o arquivo json e atribui à variável file
else {
fatalError("Couldn't find \(filename) in main bundle.")
}
do {
data = try Data(contentsOf: file) // lê o arquivo file e guarda as informações na variável data
} catch {
fatalError("Couldn't load \(filename) from main bundle:\n\(error)")
}
do {
let decoder = JSONDecoder() // diz que decoder é um leitor de json
return try decoder.decode(T.self, from: data) // decoder lê o json do arquivo data usando a classe Viagem representada por T e retorna o resultado
} catch {
fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
}
}
Espero ter ajudado!!! :)