Swiftui 映射嵌套 JSON 到平面模型
Swiftui Mapping Nested JSON to Flat Model
我需要访问 Memodel 结构的嵌套字典中的数据。来自音乐和图像词典。请需要任何帮助才能正确绘制出来,我已经尝试使用 AzampSharp 的示例 https://www.youtube.com/watch?v=b5wVIQNrI6k,但我相信我做错了什么。谢谢。
import SwiftUI
struct MemodelAPIResult: Codable {
let data: [Memodel]
enum CodingKeys: String, CodingKey {
case data = "results"
}
}
struct Memodel: Identifiable, Codable {
var id: String
var followers: String
var following: String
let music: [MemodelMusic]
let images: [MemodelImages]
}
struct MemodelMusic: Identifiable, Codable, Hashable {
var id: String
var musicfile: URL
var musicname: String
var musicartistname: String
var musicgenre: String
}
struct MemodelImages: Identifiable, Codable, Hashable {
var id: String
var albumimages: URL
var abumlikes: String
var albumviews: String
}
下面是我的视图模型中的 ObservableObject
import Foundation
import SwiftUI
import Combine
import CryptoKit
class MeViewmodel: ObservableObject {
@Published var me: [Memodel]? = nil
init() {
self.fetchme()
}
func fetchme() {
let url = ""
let session = URLSession(configuration: .default)
session.dataTask(with: URL(string: url)!) { (data, _, err) in
if let error = err{
print(error.localizedDescription)
return
}
guard let APIData = data else {
print("No Data found")
return
}
do {
let new = try JSONDecoder().decode(MemodelAPIResult.self, from: APIData)
DispatchQueue.main.async {
self.me = new.data
}
}
catch{
print(error)
}
}
.resume()
}
}
然后是项目视图
struct MeMusicItemView: View {
//E-MARK: - Properties
var me: Memodel
//E-MARK: - Body
var body: some View {
HStack {
VStack(alignment: .leading, spacing: 5) {
Text(me.music[0].musicname)
.font(.callout)
.fontWeight(.medium)
.foregroundColor(.white)
Text(me.music[0].musicartistname)
.font(.caption2)
.fontWeight(.light)
.foregroundColor(.white)
Text(me.music[0].musicgenre)
.font(.system(size: 8))
.fontWeight(.light)
.foregroundColor(.gray)
}
}
}
}
还有父视图中的 ForEach....
if let meMusicData = meMusicData.mememe {
ForEach(meMusicData) { music in
MeMusicItemView(memusic: music)
}
} else {
ProgressView()
.padding(.top, 20)
}
没有足够的信息让我真正理解你在做什么,但是
这里有一些代码,您可以根据自己的目的查看和回收:
struct ContentView: View {
@StateObject var viewModel = MeViewmodel() // <-- here your model
var body: some View {
List {
ForEach(viewModel.me) { memod in // <-- loop over the Memodel array
ForEach(memod.music) { music in // <-- loop over the MemodelMusic array
MeMusicItemView(memusic: music) // <-- display 1 MemodelMusic
}
}
}
}
}
struct MeMusicItemView: View {
//E-MARK: - Properties
@State var memusic: MemodelMusic // <-- here
//E-MARK: - Body
var body: some View {
HStack {
VStack(alignment: .leading, spacing: 5) {
Text(memusic.musicname)
.font(.callout)
.fontWeight(.medium)
.foregroundColor(.pink)
Text(memusic.musicartistname)
.font(.caption2)
.fontWeight(.light)
.foregroundColor(.green)
Text(memusic.musicgenre)
.font(.system(size: 8))
.fontWeight(.light)
.foregroundColor(.blue)
}
}
}
}
class MeViewmodel: ObservableObject {
@Published var me: [Memodel] = [] // <--- here no optional, it is easier to deal with
init() {
self.fetchme()
}
func fetchme() {
// ......
}
}
struct Memodel: Identifiable, Codable {
var id: String
var followers: String
var following: String
let music: [MemodelMusic]
let images: [MemodelImages]
}
struct MemodelMusic: Identifiable, Codable, Hashable {
var id: String
var musicfile: URL
var musicname: String
var musicartistname: String
var musicgenre: String
}
struct MemodelImages: Identifiable, Codable, Hashable {
var id: String
var albumimages: URL
var abumlikes: String
var albumviews: String
}
我需要访问 Memodel 结构的嵌套字典中的数据。来自音乐和图像词典。请需要任何帮助才能正确绘制出来,我已经尝试使用 AzampSharp 的示例 https://www.youtube.com/watch?v=b5wVIQNrI6k,但我相信我做错了什么。谢谢。
import SwiftUI
struct MemodelAPIResult: Codable {
let data: [Memodel]
enum CodingKeys: String, CodingKey {
case data = "results"
}
}
struct Memodel: Identifiable, Codable {
var id: String
var followers: String
var following: String
let music: [MemodelMusic]
let images: [MemodelImages]
}
struct MemodelMusic: Identifiable, Codable, Hashable {
var id: String
var musicfile: URL
var musicname: String
var musicartistname: String
var musicgenre: String
}
struct MemodelImages: Identifiable, Codable, Hashable {
var id: String
var albumimages: URL
var abumlikes: String
var albumviews: String
}
下面是我的视图模型中的 ObservableObject
import Foundation
import SwiftUI
import Combine
import CryptoKit
class MeViewmodel: ObservableObject {
@Published var me: [Memodel]? = nil
init() {
self.fetchme()
}
func fetchme() {
let url = ""
let session = URLSession(configuration: .default)
session.dataTask(with: URL(string: url)!) { (data, _, err) in
if let error = err{
print(error.localizedDescription)
return
}
guard let APIData = data else {
print("No Data found")
return
}
do {
let new = try JSONDecoder().decode(MemodelAPIResult.self, from: APIData)
DispatchQueue.main.async {
self.me = new.data
}
}
catch{
print(error)
}
}
.resume()
}
}
然后是项目视图
struct MeMusicItemView: View {
//E-MARK: - Properties
var me: Memodel
//E-MARK: - Body
var body: some View {
HStack {
VStack(alignment: .leading, spacing: 5) {
Text(me.music[0].musicname)
.font(.callout)
.fontWeight(.medium)
.foregroundColor(.white)
Text(me.music[0].musicartistname)
.font(.caption2)
.fontWeight(.light)
.foregroundColor(.white)
Text(me.music[0].musicgenre)
.font(.system(size: 8))
.fontWeight(.light)
.foregroundColor(.gray)
}
}
}
}
还有父视图中的 ForEach....
if let meMusicData = meMusicData.mememe {
ForEach(meMusicData) { music in
MeMusicItemView(memusic: music)
}
} else {
ProgressView()
.padding(.top, 20)
}
没有足够的信息让我真正理解你在做什么,但是 这里有一些代码,您可以根据自己的目的查看和回收:
struct ContentView: View {
@StateObject var viewModel = MeViewmodel() // <-- here your model
var body: some View {
List {
ForEach(viewModel.me) { memod in // <-- loop over the Memodel array
ForEach(memod.music) { music in // <-- loop over the MemodelMusic array
MeMusicItemView(memusic: music) // <-- display 1 MemodelMusic
}
}
}
}
}
struct MeMusicItemView: View {
//E-MARK: - Properties
@State var memusic: MemodelMusic // <-- here
//E-MARK: - Body
var body: some View {
HStack {
VStack(alignment: .leading, spacing: 5) {
Text(memusic.musicname)
.font(.callout)
.fontWeight(.medium)
.foregroundColor(.pink)
Text(memusic.musicartistname)
.font(.caption2)
.fontWeight(.light)
.foregroundColor(.green)
Text(memusic.musicgenre)
.font(.system(size: 8))
.fontWeight(.light)
.foregroundColor(.blue)
}
}
}
}
class MeViewmodel: ObservableObject {
@Published var me: [Memodel] = [] // <--- here no optional, it is easier to deal with
init() {
self.fetchme()
}
func fetchme() {
// ......
}
}
struct Memodel: Identifiable, Codable {
var id: String
var followers: String
var following: String
let music: [MemodelMusic]
let images: [MemodelImages]
}
struct MemodelMusic: Identifiable, Codable, Hashable {
var id: String
var musicfile: URL
var musicname: String
var musicartistname: String
var musicgenre: String
}
struct MemodelImages: Identifiable, Codable, Hashable {
var id: String
var albumimages: URL
var abumlikes: String
var albumviews: String
}