本文的目的是展现一种从远程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() } }