JSON API 在 Swift 中传输数据
JSON API transfer data in Swift
如何将数据从 json api 传递到 static func getAllStats()
我只需要从 JSON
传输 2 个参数 P
和 W
struct Stat: Codable, Identifiable {
var id = UUID()
let image: String
let name: String
var p: String
var w: String
let t: String
}
extension Stat {
static func getAllStats() -> [Stat] {
return [
Stat(image: "1", name: "Name1", p: "", w: "", t: "12"),
Stat(image: "71", name: "Name2", p: "", w: "", t: "13"),
Stat(image: "2", name: "Name3", p: "", w: "", t: "14")
]
}
}
class Api {
func getPost(completion: @escaping ([Stat]) -> ()) {
guard let url = URL(string: "") else {return}
URLSession.shared.dataTask(with: url) { (data, _, _) in
let posts = try! JSONDecoder().decode([Stat].self, from: data!)
DispatchQueue.main.async {
completion(posts)
}
}
.resume()
}
}
我不清楚 什么标准 你将从 Stat
的数组中插入变量 p
和 w
在 Stat
类型的其他对象中:它们是否需要匹配 ID?需要按顺序阅读吗?
我在下面建议的代码只为这 2 个变量创建了一个专用的 struct
,我称之为 PW
。这将避免将您在项目中使用的类型与从 API 下载的类型混淆。 PW
是将被解码的类型。
来自 api 的 p
和 w
根据下载的 JSON 的顺序注入到 Stat
对象中,仅用于示例目的- 但是,这不是最佳做法,因此我建议相应地调整您的代码。
该示例使用 async
来避免完成处理程序和 DispatchQueue
,但这不是必需的 - 只需使用您喜欢的方法即可。
// This is where the API will store the downloaded values
struct PW: Codable {
let p: String?
let w: String?
}
struct Stat: Codable, Identifiable {
var id = UUID()
let image: String
let name: String
// Replace 2 variables of type string with one variable of type PW
var pw: PW
let t: String
}
extension Stat {
// This will allow the code to read p and w in a convenient way
var p: String { pw.p ?? "" }
var w: String { pw.w ?? "" }
// async just to match the function in the Api class, but you
// can use your own code
static func getAllStats() async -> [Stat] {
// Get the array of PW (with p and w values) from the api
let pws = await Api().getPost()
return [
// Each object will store p and w values based on the order received:
// this is NOT a best practice, a clear and unique criteria should be used
Stat(image: "1", name: "Name1", pw: pws[0], t: "12"),
Stat(image: "71", name: "Name2", pw: pws[1], t: "13"),
Stat(image: "2", name: "Name3", pw: pws[2], t: "14")
]
}
}
// This class is just for example purposes, implement your own code as you wish
class Api {
// async just to avoid completion and DispatchQueue
func getPost() async -> [PW] {
guard let url = URL(string: "https://...") else { return [] }
let request = URLRequest(url: url)
do {
let (data, response) = try await URLSession.shared.data(for: request)
guard let httpResponse = response as? HTTPURLResponse,
(200...299).contains(httpResponse.statusCode) else {
print("Error: HTTP response =\n\(response.debugDescription)")
return []
}
// Decode type PW, not Stat
let posts = try! JSONDecoder().decode([PW].self, from: data)
return posts
} catch {
print("Oops: something went wrong!")
return []
}
}
}
// Example of a view, just to show how to use the code
struct MyView: View {
@State private var stats = [Stat]()
var body: some View {
VStack {
ForEach(stats) { stat in
VStack {
Text(stat.name)
Text(stat.p)
Text(stat.w)
}
}
}
.task {
stats = await Stat.getAllStats()
}
}
}
如何将数据从 json api 传递到 static func getAllStats()
我只需要从 JSON
传输 2 个参数P
和 W
struct Stat: Codable, Identifiable {
var id = UUID()
let image: String
let name: String
var p: String
var w: String
let t: String
}
extension Stat {
static func getAllStats() -> [Stat] {
return [
Stat(image: "1", name: "Name1", p: "", w: "", t: "12"),
Stat(image: "71", name: "Name2", p: "", w: "", t: "13"),
Stat(image: "2", name: "Name3", p: "", w: "", t: "14")
]
}
}
class Api {
func getPost(completion: @escaping ([Stat]) -> ()) {
guard let url = URL(string: "") else {return}
URLSession.shared.dataTask(with: url) { (data, _, _) in
let posts = try! JSONDecoder().decode([Stat].self, from: data!)
DispatchQueue.main.async {
completion(posts)
}
}
.resume()
}
}
我不清楚 什么标准 你将从 Stat
的数组中插入变量 p
和 w
在 Stat
类型的其他对象中:它们是否需要匹配 ID?需要按顺序阅读吗?
我在下面建议的代码只为这 2 个变量创建了一个专用的 struct
,我称之为 PW
。这将避免将您在项目中使用的类型与从 API 下载的类型混淆。 PW
是将被解码的类型。
p
和 w
根据下载的 JSON 的顺序注入到 Stat
对象中,仅用于示例目的- 但是,这不是最佳做法,因此我建议相应地调整您的代码。
该示例使用 async
来避免完成处理程序和 DispatchQueue
,但这不是必需的 - 只需使用您喜欢的方法即可。
// This is where the API will store the downloaded values
struct PW: Codable {
let p: String?
let w: String?
}
struct Stat: Codable, Identifiable {
var id = UUID()
let image: String
let name: String
// Replace 2 variables of type string with one variable of type PW
var pw: PW
let t: String
}
extension Stat {
// This will allow the code to read p and w in a convenient way
var p: String { pw.p ?? "" }
var w: String { pw.w ?? "" }
// async just to match the function in the Api class, but you
// can use your own code
static func getAllStats() async -> [Stat] {
// Get the array of PW (with p and w values) from the api
let pws = await Api().getPost()
return [
// Each object will store p and w values based on the order received:
// this is NOT a best practice, a clear and unique criteria should be used
Stat(image: "1", name: "Name1", pw: pws[0], t: "12"),
Stat(image: "71", name: "Name2", pw: pws[1], t: "13"),
Stat(image: "2", name: "Name3", pw: pws[2], t: "14")
]
}
}
// This class is just for example purposes, implement your own code as you wish
class Api {
// async just to avoid completion and DispatchQueue
func getPost() async -> [PW] {
guard let url = URL(string: "https://...") else { return [] }
let request = URLRequest(url: url)
do {
let (data, response) = try await URLSession.shared.data(for: request)
guard let httpResponse = response as? HTTPURLResponse,
(200...299).contains(httpResponse.statusCode) else {
print("Error: HTTP response =\n\(response.debugDescription)")
return []
}
// Decode type PW, not Stat
let posts = try! JSONDecoder().decode([PW].self, from: data)
return posts
} catch {
print("Oops: something went wrong!")
return []
}
}
}
// Example of a view, just to show how to use the code
struct MyView: View {
@State private var stats = [Stat]()
var body: some View {
VStack {
ForEach(stats) { stat in
VStack {
Text(stat.name)
Text(stat.p)
Text(stat.w)
}
}
}
.task {
stats = await Stat.getAllStats()
}
}
}