Riempire una List da JSON in SwiftUI

Mattepuffo's logo
Riempire una List da JSON in SwiftUI

Riempire una List da JSON in SwiftUI

Oggi vediamo come riempire una List da JSON in Swift e SwiftUI.

Partiamo dal JSON remoto che ha questa struttura:

    {
    "books": [{
        "id": "87",
        "title": "2001 odissea nello spazio",
        "author_id": null,
        "author": "arthur c. clarke",
        "editor_id": null,
        "editor": "longanesi",
        "price": "0.00",
        "isbn": "",
        "note": ""
    }, {
        "id": "87",
        "title": "2001 odissea nello spazio",
        "author_id": null,
        "author": "arthur c. clarke",
        "editor_id": null,
        "editor": "longanesi",
        "price": "0.00",
        "isbn": "",
        "note": ""
    }]
}

Quello a cui dobbiamo stare attenti è che il JSON non inizia con un array, ma con un oggetto, di cui dobbiamo tener conto.

Cominciamo dalle struct che rappresentano i dati:

// Book.swift

import Foundation

struct BookList: Decodable {
    let books : [Book]
}

struct Book: Decodable, Identifiable {
    
    public var id: String;
    public var title: String;
    public var isbn: String;
    
    enum CodingKeys: String, CodingKey {
        case id = "id";
        case title = "title";
        case isbn = "isbn";
    }
    
}

La prima struct è sostanzialmente la root del JSON; la seconda sarà l'array che contiene i nostri oggetti.

Qui sotto la classe da cui prendiamo i dati in remoto:

// GetBooks.swift

import Foundation

public class GetBooks: ObservableObject {
    
    @Published var books = [Book]();
    
    init() {
        load();
    }
    
    func load() {
        let url = URL(string: "https://www.sito.com/api/file.php")!;
        
        URLSession.shared.dataTask(with: url) {
            (data, response, error) in
            do {
                if let d = data {
                    let decodedLists = JSONDecoder();
                    decodedLists.keyDecodingStrategy = .convertFromSnakeCase;
                    let dec = try decodedLists.decode(BookList.self, from: d);
                    DispatchQueue.main.async {
                        self.books = dec.books;
                    }
                } else {
                    print("Non ci sono libri");
                }
            } catch {
                print(error)
            }
            
        }.resume();
        
    }
}

Infine andiamo a vedere il nostro layout:

// ContentView.swift

import SwiftUI

struct ContentView: View {
    
    @ObservedObject var getBooks = GetBooks();
    
    var body: some View {
        VStack {
            List(getBooks.books) { book in
                VStack (alignment: .leading) {
                    Text(book.title)
                    Text(book.isbn)
                        .font(.system(size: 11))
                        .foregroundColor(Color.gray)
                }
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView();
    }
}

Ovviamente questo va bene per il tipo di struttura che ho io; per altre strutture dovete fare dei cambiamenti nel codice.

Enjoy!


Share this Post

Commentami!