aadityaaa
aadityaaa

Reputation: 43

How to show data from Api inside my SwiftUI app

I was making this app which would show certain information about upcoming animes, am using jikan API for this and it doesn't require any Authentication or any key

here is how the API look -

{
  "request_hash": "request:top:3506eaba6445f7ad5cc2f78417bf6ed916b6aaad",
  "request_cached": true,
  "request_cache_expiry": 43675,
  "top": [
    {
      "mal_id": 40356,
      "rank": 1,
      "title": "Tate no Yuusha no Nariagari Season 2",
      "url": "https://myanimelist.net/anime/40356/Tate_no_Yuusha_no_Nariagari_Season_2",
      "image_url": "https://cdn.myanimelist.net/images/anime/1245/111800.jpg?s=7302aaeb3bc4e1433b32d094e9d6f6f0",
      "type": "TV",
      "episodes": {},
      "start_date": "Apr 2022",
      "end_date": {},
      "members": 300837,
      "score": 0
    },
    {
      "mal_id": 48583,
      "rank": 2,
      "title": "Shingeki no Kyojin: The Final Season Part 2",
      "url": "https://myanimelist.net/anime/48583/Shingeki_no_Kyojin__The_Final_Season_Part_2",
      "image_url": "https://cdn.myanimelist.net/images/anime/1989/116577.jpg?s=f6312bda2e67f86595936d0264696a91",
      "type": "TV",
      "episodes": {},
      "start_date": "Jan 2022",
      "end_date": {},
      "members": 253849,
      "score": 0
    },

this is how I have written my code and for some reason when I run the app am just getting a plain blank white screen and also it prints out the last print statement that I have added saying " Fetch Failed: Unknown error " please help me with this

 import SwiftUI


struct Response: Codable{
    var top: [Result]
    
}

struct Result: Codable {
    
    var mal_id: Int
    var rank: Int
    var title: String
    var type: String
    var start_date: String
    
}

struct ContentView: View {
    
    func loadData() {

        guard let url = URL(string: "https://api.jikan.moe/v3/top/anime/1/upcoming") else {
            print("Invalid URL")
            return
        }
        
        let request = URLRequest(url: url)
        
        URLSession.shared.dataTask(with: request) { data, response, error in
            if let data = data {
                if let decodedResponse = try? JSONDecoder().decode(Response.self, from: data) {
                    // we have good data – go back to the main thread
                    DispatchQueue.main.async {
                        // update our UI
                        self.top = decodedResponse.top
                    }

                    // everything is good, so we can exit
                    return
                }
            }

            // if we're still here it means there was a problem
            print("Fetch failed: \(error?.localizedDescription ?? "Unknown error")")
        }.resume()
    }
    
    @State private var top = [Result]()
    var body: some View {
        ScrollView {
            List(top, id: \.mal_id) { item in
                        VStack(alignment: .leading) {
                            Text(item.title)
                                .font(.headline)
                            Text(String("\(item.rank)"))
                                .font(.headline)
                            Text(item.type)
                                .font(.headline)
                            Text(item.start_date)
                                .font(.headline)
                            
                        }
                    }
                       }
           
        .onAppear(perform: loadData)
    }
}

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

Upvotes: 1

Views: 1681

Answers (1)

cedricbahirwe
cedricbahirwe

Reputation: 1396

First, The problem is encountered when decoding your data, it looks like some fields are coming as null, so you should decode them as optional, in this case I found that var start_date: String field is the one causing the problem, so just make sure you make it optional: var start_date: String?

And Second, You don't need to put the List inside the ScrollView because by default a List is a type of ScrollView.

Model: (make some files optional)

struct Result: Codable {
    var mal_id: Int
    var rank: Int
    var title: String
    var type: String
    var start_date: String?
}

Body Content: (removed the scrollview)

var body: some View {
    List(top, id: \.mal_id) { item in
        VStack(alignment: .leading) {
            Text(item.title)
                .font(.headline)
            Text(String("\(item.rank)"))
                .font(.headline)
            Text(item.type)
                .font(.headline)
            Text(item.start_date ?? "")
                .font(.headline)
            
        }
    }
    .onAppear(perform: loadData)
}

Upvotes: 1

Related Questions