SwiftUI 中級之List顯示遠程Json文件(2020年教程)

SwiftUI 中級之List顯示遠程Json文件(2020年教程)

本文的目的是展現一種從遠程JSON文件獲取數據並將其顯示在SwiftUI中的列表上的簡單方法。

數據介紹

下面是咱們json文件的格式git

[{
    "id": 5,
    "title": "Joker",
    "year": "2019",
    "image": "",
    "created_at": "2019-10-06T17:55:21.374Z",
    "updated_at": "2019-10-06T17:55:21.374Z"
}, {
    "id": 1,
    "title": "Pulp Fiction",
    "year": "1994",
    "image": "",
    "created_at": "2019-10-06T15:26:36.675Z",
    "updated_at": "2019-10-06T18:05:31.649Z"
}, {
    "id": 4,
    "title": " The Godfather ",
    "year": "1972",
    "image": "",
    "created_at": "2019-10-06T15:27:38.123Z",
    "updated_at": "2019-10-06T18:05:50.242Z"
}, {
    "id": 6,
    "title": "The Dark Knight ",
    "year": "2008",
    "image": "",
    "created_at": "2019-10-06T18:06:12.933Z",
    "updated_at": "2019-10-06T18:06:12.933Z"
}, {
    "id": 7,
    "title": "Fight Club",
    "year": "1999",
    "image": "",
    "created_at": "2019-10-06T18:06:33.096Z",
    "updated_at": "2019-10-06T18:06:33.096Z"
}, {
    "id": 8,
    "title": " Inception",
    "year": "2010",
    "image": "",
    "created_at": "2019-10-06T18:06:52.034Z",
    "updated_at": "2019-10-06T18:06:52.034Z"
}, {
    "id": 2,
    "title": "The Matrix ",
    "year": "1999",
    "image": "",
    "created_at": "2019-10-06T15:26:48.042Z",
    "updated_at": "2019-10-06T18:08:00.902Z"
}, {
    "id": 3,
    "title": "The Shawshank Redemption ",
    "year": "1984",
    "image": "",
    "created_at": "2019-10-06T15:26:59.572Z",
    "updated_at": "2019-10-06T18:08:47.637Z"
}]

預期效果

Jietu20200124-094043@2x.jpg

編碼

首先,咱們須要爲Movie定義模型,在這種狀況下,該模型是具備Decodable和Identifiable協議的struct。Decodable可以從JSON文件中對其進行解碼,Identifiable可以與List一塊兒列出。List能夠像UITableViewController同樣顯示可標識集合中的數據列表。
struct Movie: Decodable, Identifiable {
    public var id: Int
    public var name: String
    public var released: String
    
    enum CodingKeys: String, CodingKey {
           case id = "id"
           case name = "title"
           case released = "year"
        }
}

CodingKeys可以將JSON key名稱與您建立的Model的變量名稱進行映射。在這種狀況下,我將其命名爲Release而不是年份,只是爲了代表您能夠在模型中使用本身的名稱,只要您在Coding Keys中定義它便可。github

下面咱們將編碼讀取數據並進行解碼的代碼
public class MovieFetcher: ObservableObject {
    @Published var movies = [Movie]()
    
    init(){
        load()
    }
    
    func load() {
        let url = URL(string: "https://gist.githubusercontent.com/rbreve/60eb5f6fe49d5f019d0c39d71cb8388d/raw/f6bc27e3e637257e2f75c278520709dd20b1e089/movies.json")!
    
        URLSession.shared.dataTask(with: url) {(data,response,error) in
            do {
                if let d = data {
                    let decodedLists = try JSONDecoder().decode([Movie].self, from: d)
                    DispatchQueue.main.async {
                        self.movies = decodedLists
                    }
                }else {
                    print("No Data")
                }
            } catch {
                print ("Error")
            }
            
        }.resume()
         
    }
}
Combine框架提供了一個聲明性的Swift API,用於隨時間處理值。這些值能夠表示多種異步事件。 Combine聲明發布者公開隨時間變化的值,訂閱者從發佈者那裏接收這些值。
@ObervableObject:具備發佈者功能的一種對象,該對象在對象更改以前發出。默認狀況下,@ObservableObject會合成一個objectWillChange發佈者,該發佈者會在其@Published屬性中的任何一個發生更改以前發出更改的值。
@Published修飾movies數組後,當movies發生改變是將通知全部的ObserableObject。

load()方法從網絡異步獲取JSON數據,一旦數據加載完畢,咱們便將其分配給movie數組。movie數組更改時,它將向訂戶發送事件。json

struct ContentView: View {
    @ObservedObject var fetcher = MovieFetcher()
    
    var body: some View {
        VStack {
            List(fetcher.movies) { movie in
                VStack (alignment: .leading) {
                    Text(movie.name)
                    Text(movie.released)
                        .font(.system(size: 11))
                        .foregroundColor(Color.gray)
                }
            }
        }
    }
}

完整代碼

import Foundation
import SwiftUI
import Combine
 
public class MovieFetcher: ObservableObject {

    @Published var movies = [Movie]()
    
    init(){
        load()
    }
    
    func load() {
        let url = URL(string: "https://gist.githubusercontent.com/rbreve/60eb5f6fe49d5f019d0c39d71cb8388d/raw/f6bc27e3e637257e2f75c278520709dd20b1e089/movies.json")!
    
        URLSession.shared.dataTask(with: url) {(data,response,error) in
            do {
                if let d = data {
                    let decodedLists = try JSONDecoder().decode([Movie].self, from: d)
                    DispatchQueue.main.async {
                        self.movies = decodedLists
                    }
                }else {
                    print("No Data")
                }
            } catch {
                print ("Error")
            }
            
        }.resume()
         
    }
}

struct Movie: Codable, Identifiable {
    public var id: Int
    public var name: String
    public var released: String
    
    enum CodingKeys: String, CodingKey {
           case id = "id"
           case name = "title"
           case released = "year"
        }
}


struct ListJsonView: View {
    @ObservedObject var fetcher = MovieFetcher()
    
    var body: some View {
        VStack {
            List(fetcher.movies) { movie in
                VStack (alignment: .leading) {
                    Text(movie.name)
                    Text(movie.released)
                        .font(.system(size: 11))
                        .foregroundColor(Color.gray)
                }
            }
        }
    }
}

 


struct ListJsonView__Previews: PreviewProvider {
    static var previews: some View {
        ListJsonView()
    }
}

參考文件

相關文章
相關標籤/搜索