本文的目的是展示一种从远程JSON文件获取数据并将其显示在SwiftUI中的列表上的简单方法。
下面是我们json文件的格式
[{
"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中定义它即可。
下面我们将编码读取数据并进行解码的代码
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数组更改时,它将向订户发送事件。
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()
}
}