0

I need to access the data in the nested dictionary of the Memodel struct. From both the music and image dictionary. Please any help is needed to map out correctly, i have tried using AzampSharp's example https://www.youtube.com/watch?v=b5wVIQNrI6k but i believe i am doing something wrong. Thanks.

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
    }

Below is my ObservableObject in my View Model

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()
    }
    
}

And then the item view

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)
                    }
                }
    }
}

And also the ForEach in the parent View....

if let meMusicData = meMusicData.mememe {
                    ForEach(meMusicData) { music in
                        MeMusicItemView(memusic: music)
                    }
                    } else {
                        ProgressView()
                            .padding(.top, 20)
                    }
EMPIRE
  • 57
  • 7
  • What exactly is not working? What error do you get? You could try `var musicfile: String` and `var albumimages: String` – workingdog support Ukraine Jan 08 '22 at 06:21
  • @workingdog when i try to get access to the Memodel dictionary in a struct via "var me: Memodel" i can access for example "me.followers" but cannot access the nested dictionary! for example "me.music.musicfile " – EMPIRE Jan 08 '22 at 06:33
  • 1
    `me.music` is an array. You acces array using an index, like this: `me.music[0].musicfile`. – workingdog support Ukraine Jan 08 '22 at 06:39
  • @workingdog yeah it worked, thanks. but there is another problem the array has over 10 entrys, in the input view using me.music[<#Int#>].musicfile requires you to return an integer, i would like to return all entries since i am using a forEach in the main view. – EMPIRE Jan 08 '22 at 07:27
  • I don't see any "input view" nor a `ForEach` in your code. You will have to show more code, and explain what your question is. I suggest you go through Apple's SwiftUI Tutorials https://developer.apple.com/tutorials/swiftui. – workingdog support Ukraine Jan 08 '22 at 08:14
  • `@EMPIRE`, no offense, but I feel that you don't have a good grip on using arrays of data in SwiftUI. You call them `dictionary` in your question. You have asked similar questions before, like: https://stackoverflow.com/questions/70487312/swiftui-getting-data-from-a-nested-json-struct and https://stackoverflow.com/questions/70407469/json-data-format-in-swift In addition to Apple SwiftUI Tutorials, read the basic use of Swift. – workingdog support Ukraine Jan 08 '22 at 08:30
  • @workingdog none taken, i do understand the learning process. I have updated the question with the item view and the forEach i wrote earlier. – EMPIRE Jan 08 '22 at 09:23
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/240859/discussion-between-empire-and-workingdog). – EMPIRE Jan 08 '22 at 09:25

1 Answers1

1

There is not enough info for me to really understand what you are doing, but here is some code you can have a look at and recycle for your purpose:

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
}