0

I'm working on my first app, which loads a JSON with the elements that need to be displayed. At the moment everything seems to work, except a few details which I hope you can help me solve:

  • My interface is composed of a TabView contained within a NavigationView (which contains a button that brings up a SheetView) ... if I go to the Tab that brings up the list with the contents downloaded from the JSON everything works, but if I move to another Tab and then I go back to the one that displays the JSON, the data is no longer visible. I obviously inserted in the code (where necessary) ObservableObject, ObservedObject and onAppear that should reload the JSON, but without success ... it is clear that something is missing ...
  • How could I go about displaying a list of categories starting from a JSON field? Let me explain, I used the "autore" field of the JSON to define categories, so I would need to first display a list of these categories, then, entering the respective categories, I have to display a list with the elements relating to the selected category and then obviously the DetailView for the single elements.

Of course, since is my first time writing here, ask me everything you need to help me solving the problem...

This is the relevant code:

Code: BussoModel.swift

import SwiftUI

class BussoModel: Identifiable {

    var id: UUID = UUID()
    var titolo: String = ""
    var autore: String = ""
    var testo: String = ""
    var data: String = ""
    var extra1: String = ""
    var extra2: String = ""
    var fotoUrl: String = ""
}

Code: DownloadManager.swift

import SwiftUI
import Combine
import Alamofire

class DownloadManager: ObservableObject {

    let objectWillChange = PassthroughSubject<Void, Never>()

    var storage : [BussoModel] = []

    func scaricaJSON() {
    
        AF.request("http://geniuspointfrezza.altervista.org/index.php?json=1").responseJSON { response in
        
            if let errore = response.error {
                debugPrint(errore.localizedDescription)
                return
            }
        
            guard let ilJson = response.value else { return }
        
            guard let json = JSON(ilJson).array else { return }
        
            self.storage = []
        
            let totale = json.count
        
            for i in 0..<totale {
            
                let busso = BussoModel()
            
                if let titolo = json[i]["titolo"].string {
                    busso.titolo = titolo
                }
            
                if let autore = json[i]["autore"].string {
                    busso.autore = autore
                }
            
                if let testo = json[i]["testo"].string {
                    busso.testo = testo
                }
            
                if let data = json[i]["data"].string {
                    busso.data = data
                }
            
                if let extra1 = json[i]["extra1"].string {
                    busso.extra1 = extra1
                }
            
                if let extra2 = json[i]["extra2"].string {
                    busso.extra2 = extra2
                }
            
                if let foto = json[i]["fotoUrl"].string {
                    busso.fotoUrl = foto
                }
            
                self.storage.append(busso)
            
            }
        
            self.objectWillChange.send()
        
        }
    
    }

}

Code: CategoryView.swift

import SwiftUI
import URLImage

struct CategoryView: View {

    @ObservedObject var dm: DownloadManager

    var body: some View {
        List {
            ForEach(dm.storage) { busso in
                NavigationLink(
                    destination: DetailView(busso: busso)) {
                    HStack {
                        URLImage(URL(string: busso.fotoUrl) ?? furl)
                            .resizable()
                            .aspectRatio(contentMode: .fit)
                            .clipped()
                            .padding()
                    
                        VStack(alignment: .leading) {
                            Text(busso.titolo)
                                .font(.headline)
                            Text(busso.autore)
                                .font(.subheadline)
                        }
                    
                        Spacer().layoutPriority(-0.1)
                    
                    }
                    .frame(minWidth: 0, maxWidth: .infinity)
                    .frame(height: 50)
                }
            }
        }
        .onAppear {
            self.dm.scaricaJSON()
        }
    }
}

struct CategoryView_Previews: PreviewProvider {
    static var previews: some View {
        CategoryView(dm: DownloadManager())
    }
}

Code: MainTabView.swift

import SwiftUI

struct MainTabView: View {

    @State private var selected = 0

    var body: some View {
        TabView(selection: $selected) {
            HomeView()
                .tabItem {
                    Image(systemName: (selected == 0 ? "house.fill" :         "house"))
                    Text("Home")
                }.tag(0)
            CategoryView(dm: DownloadManager())
                .tabItem {
                    Image(systemName: (selected == 1 ? "text.justify" : "text.justify"))
                    Text("Categorie")
                }.tag(1)
            Text("Galleria?")
                .tabItem {
                    Image(systemName: (selected == 2 ? "photo.fill" : "photo"))
                    Text("Galleria")
                }.tag(2)
            Text("Preferiti?")
                .tabItem {
                    Image(systemName: (selected == 3 ? "star.fill" : "star"))
                    Text("Preferiti")
                }.tag(3)
        }
        .accentColor(.white)
        .onAppear() {
            UINavigationBar.appearance().barTintColor = UIColor(red: 115.0/255.0, green: 90.0/255.0, blue: 143.0/255.0, alpha: 1.0)
            UINavigationBar.appearance().titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white]
            UITabBar.appearance().barTintColor = UIColor(red: 115.0/255.0, green: 90.0/255.0, blue: 143.0/255.0, alpha: 1.0)
        }
    }
}

struct MainTabView_Previews: PreviewProvider {
    static var previews: some View {
        MainTabView()
    }
}

Code: ContentView.swift

import SwiftUI
import URLImage

let furl = URL(fileURLWithPath: "path")

struct ContentView: View {

    @State var showInfoView = false

    var body: some View {
        NavigationView {
            MainTabView()
                .sheet(isPresented: $showInfoView) {
                    InfoView(showInfoView: $showInfoView)
                }
                .navigationBarTitle((Text("ViviBusso")), displayMode:     .inline)
                .navigationBarItems(leading:
                                        Button(action: {
                                            debugPrint("QR Code")
                                        }) {
                                            Image(systemName: "qrcode")
                                        }
                    .foregroundColor(.white), trailing: Button(action: {
                        self.showInfoView.toggle()
                    }) {
                        Image(systemName: "info.circle")
                    }
                    .foregroundColor(.white)
                )
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Waiting for suggestions, thanks!

EDIT: New code tested:

import SwiftUI
import URLImage

struct Busso: Codable, Identifiable {
    public var id: UUID
    public var titolo: String
    public var autore: String
    public var testo: String
    public var data: String
    public var extra1: String
    public var extra2: String
    public var foto: String
    public var fotoUrl: String
}

class FetchBusso: ObservableObject {

    @Published var Bussos = [Busso]()
    
    init() {
        let url = URL(string: "https://geniuspointfrezza.altervista.org/index.php?json=1")!

        URLSession.shared.dataTask(with: url) {(data, response, error) in
            do {
                if let bussoData = data {

                    let decodedData = try JSONDecoder().decode([Busso].self, from: bussoData)
                    DispatchQueue.main.async {
                        self.Bussos = decodedData
                    }
                } else {
                    print("No data")
                }
            } catch {
                print("Error")
            }
        }.resume()
    }
}

struct CategoryView: View {
    
    @ObservedObject var fetch = FetchBusso()
    var body: some View {
        VStack {
            List(fetch.Bussos) { todo in
                VStack(alignment: .leading) {
                    Text(todo.titolo)
                }
            }
        }
    }
}


struct CategoryView_Previews: PreviewProvider {
    static var previews: some View {
        CategoryView()
    }
}
10
  • You should ask one question and not two and you need to provide much more details and of course relevant code Commented Jan 4, 2021 at 20:07
  • OK, I'll edit the original post so you can get a better idea of what's going on... As for the two questions, in my opinion they are somehow related to each other, that's why I posted them both... Commented Jan 4, 2021 at 21:18
  • I think a great deal of your issue is that you are not properly dealing with your JSON. See this answer for a modern, well constructed async fetch. Then look at my answer above that details a struct to properly parse the data. This result in the data being in a nice struct for your use. If you still can't make it work at that point, ask a new question and show the code you have. P.S. check this link for guidance on asking questions. Commented Jan 5, 2021 at 13:47
  • @Yrb I added my code in the original post, could you please tell me what changes I need to make, and where? Keep in mind, is my first app, so I still don't know a lot of things... Commented Jan 5, 2021 at 23:41
  • Part of the learning is beating it into your head. The links I posted in my comment pretty well cover it. The code in the first link is pretty much copy and paste. The second link shows you how to put together the struct for decoding the JSON. It really is all there. Commented Jan 5, 2021 at 23:45

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.