本文的目的是展現一種從遠程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" }]
首先,咱們須要爲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() } }