Search code examples
jsonswiftswiftui

SwiftUI JSON fetch Data from Wordpress API


I need help on my structs ( og_image Link-> url )

My struct so far

struct UpcomingGames: Codable,Identifiable {
    var id: Int
    let link: String
    let title: Rendered
    let yoastHeadJSON: Title
    
    enum CodingKeys: String, CodingKey {
        case id
        case link
        case title
        case yoastHeadJSON = "yoast_head_json"
    }
}

struct Rendered: Codable {
     var rendered: String
}

struct Title: Codable {
    let title: String
    let description: String
    let author: String
    let ogimage: [OgImage]
    
    enum CodingKeys: String, CodingKey {
        case title
        case description
        case author
        case ogimage = "og_image"
    }
}

struct OgImage: Codable {
    let width, height: Int
    let url: String
    let type: String
}

everything works fine, but I can't access to og_image-> url

my Code

struct ContentView: View {
    
    @State var upcominggames = [UpcomingGames]()
    @State private var queryString = ""
    @State var showSidebar = false
    @State var showSettings = false

    var body: some View {
        NavigationView {
            List {
                ForEach(upcominggames, id: \.id) { item in
                    NavigationLink(destination: details(item: item)){
                        HStack {
                                Text(item.yoastHeadJSON.title)
                                    .font(.headline)
                                    .bold()
                                    .lineLimit(2)
                                Text(item.yoastHeadJSON.description)
                                    .font(.subheadline)
                                    .lineLimit(2)
                                    .padding(.bottom,10)
                                HStack {
                                    Image("icon_comment.png.pagespeed.ce.PPGg0gnQ7a")
                                    Text("12")
                                        .font(.caption)
                                    Spacer()
                                    Text("Weiterlesen")
                                        .padding(4)
                                        .font(.caption)
                                        .background(Color.gray)
                                        .foregroundColor(Color.white)
                                        .padding(.bottom,5)
                    
                                    //Text(item.yoastHeadJSON.ogimage)
                                    //Text(item.yoast_head_json.og_image)
                                    //Text(item.yoast_head_json.og_image.)
                                }
                            }
                        }
                    }
                }
            }
            .listStyle(.grouped)
            .onAppear(perform: loadData)
            .navigationTitle("Xbox News")
            .navigationBarTitleDisplayMode(.automatic)
            
            /*
             Toolbar
             */
            .toolbar {
                ToolbarItem(placement: .principal) {
                    HStack {
                        Button("",systemImage: "line.3.horizontal", action: { showSidebar = true })
                            .sheet(isPresented: $showSidebar, content: { Einstellungen() })
                        Spacer()
                        Image("logo")
                            .resizable()
                            .frame(width: 60, height: 40,alignment: .center)
                            .padding(.top,-5)
                        Spacer()
                        Button("",systemImage: "gearshape", action: { showSettings = true })
                            .sheet(isPresented: $showSettings, content: { Einstellungen() })
                    }
                }
            }
            /*
             Toolbar Ende
             */
        }

        
        
        
        
       
        
        
        
        /*.searchable(text: $queryString, prompt: "Suche...") {
            
        }*/
        
        
    }

    
    
    
    func loadData() {
        guard let url = URL(string: "https://xboxdynasty.de/wp-json/wp/v2/posts/") else {
            print("Invalid URL")
            return
        }
        let request = URLRequest(url: url)
        URLSession.shared.dataTask(with: request) {data, response, error in
            if let data = data {
                let decoder = JSONDecoder()
                decoder.dataDecodingStrategy = .base64
                
                if let decodedResponse = try?
                    decoder.decode([UpcomingGames].self, from: data) {
                    DispatchQueue.main.async {
                        self.upcominggames = decodedResponse
                    }
                    return
                }
            }
            print("Fetch failed: \(error?.localizedDescription ?? "Uknown error")")
        }.resume()
    } // Ende func loadData
    
    
    
    
        
}

There is something wrong with my struct

Here's the Link to the API

https://xboxdynasty.de/wp-json/wp/v2/posts/

i have tried QuickType for the struct but nothing helps

i am a beginner in Swift


Solution

  • Try this approach to ...access to og_image-> url, making OgImage Identifiable, and using a ForEach(item.yoastHeadJSON.ogimage) as shown in the example code.

    Also note the updated func loadData().

    struct OgImage: Codable, Identifiable {  // <--- here
        let id = UUID()  // <--- here
        
        let width, height: Int
        let url: String
        let type: String
        
        enum CodingKeys: String, CodingKey {  // <--- here
            case width, height, url, type
        }
    }
    
    struct ContentView: View {
        
        @State private var upcominggames = [UpcomingGames]()
        @State private var queryString = ""
        @State private var showSidebar = false
        @State private var showSettings = false
        
        var body: some View {
            NavigationView {
                List {
                    ForEach(upcominggames, id: \.id) { item in
                        NavigationLink(destination: Text(item.title.rendered)){  // <--- for my testing
                            HStack {
                                Text(item.yoastHeadJSON.title)
                                    .font(.headline)
                                    .bold()
                                    .lineLimit(2)
                                Text(item.yoastHeadJSON.description)
                                    .font(.subheadline)
                                    .lineLimit(2)
                                    .padding(.bottom,10)
                                HStack {
                                    Image(systemName: "globe")
                                    Text("12")
                                        .font(.caption)
                                    Spacer()
                                    Text("Weiterlesen")
                                        .padding(4)
                                        .font(.caption)
                                        .background(Color.gray)
                                        .foregroundColor(Color.white)
                                        .padding(.bottom,5)
    
                                }
                            }
                        }
                        
                        // --- here, ogimage is an array of OgImage
                        // ForEach(item.yoastHeadJSON.ogimage) { img in
                            // Text(img.url).foregroundColor(Color.red)
                       // }
    
                    // --- for the actual images
                    ForEach(item.yoastHeadJSON.ogimage) { img in
                        AsyncImage(url: URL(string: img.url)) { image in
                            image.resizable().frame(width: 123, height: 123)
                        } placeholder: {
                            ProgressView()
                        }
                    }
    
    
                    }
                }
            }
            .listStyle(.grouped)
            .onAppear(perform: loadData)
            .navigationTitle("Xbox News")
            .navigationBarTitleDisplayMode(.automatic)
    
            .toolbar {
                ToolbarItem(placement: .principal) {
                    HStack {
                        Button("",systemImage: "line.3.horizontal", action: { showSidebar = true })
                            .sheet(isPresented: $showSidebar, content: { Text("sheet") })
                        Spacer()
                        Image("logo")
                            .resizable()
                            .frame(width: 60, height: 40,alignment: .center)
                            .padding(.top,-5)
                        Spacer()
                        Button("",systemImage: "gearshape", action: { showSettings = true })
                            .sheet(isPresented: $showSettings, content: { Text("sheet") })
                    }
                }
            }
        }
        
    func loadData() {
            guard let url = URL(string: "https://xboxdynasty.de/wp-json/wp/v2/posts/") else {
                print("Invalid URL")
                return
            }
            let request = URLRequest(url: url)
            
            URLSession.shared.dataTask(with: request) { data, response, error in
                if let data = data {
                    // --- here
                    do {
                        upcominggames = try JSONDecoder().decode([UpcomingGames].self, from: data)
                    } catch {
                        print("error: \(error)")
                    }
                } else {
                    print("Fetch failed: \(error?.localizedDescription ?? "Uknown error")")
                }
            }.resume()
            
        } // Ende func loadData
    }