1

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

aadityaaa
  • 43
  • 6
  • Don't `try? `. You ignore a possible and very descriptive error. Replace `try?` with `try` and a `do - catch` block and `print(error)` in the `catch` clause – vadian Jul 20 '21 at 17:11
  • thanks for helping, it's resolved now, when I did what you told me to it threw an error saying. " Invalid conversion from throwing function of type '(Data?, URLResponse?, Error?) throws -> Void' to non-throwing function type '(Data?, URLResponse?, Error?) -> Void' " – aadityaaa Jul 20 '21 at 17:58
  • so I just went along with the other solution and now it works – aadityaaa Jul 20 '21 at 18:00
  • As I said you have to write `do { let decodedResponse = try .... } catch { print(error) }` – vadian Jul 20 '21 at 18:09

1 Answers1

1

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)
}
cedricbahirwe
  • 1,274
  • 4
  • 15
  • thanks a lot, it works now, I have one last question though I want to include the image as well since there is an image URL too when I add that property as a string inside my struct and when I use the Image(item.image_url) inside my view it says cannot find the image in the asset folder, how to resolve this !? – aadityaaa Jul 20 '21 at 17:57
  • That is because `Image` view is convenient to load images you already have locally (for example in your assets folder) – cedricbahirwe Jul 20 '21 at 18:05
  • when it comes to loading images from a remote URL, There are various ways to achieve that, of course, it's possible to easily load images in `iOS 15` (https://stackoverflow.com/questions/60677622/how-to-display-image-from-a-url-in-swiftui) – cedricbahirwe Jul 20 '21 at 18:08
  • but if you want to run lower versions (prior to iOS 15), you may need to rely on other solutions , I recommend (https://www.hackingwithswift.com/forums/swiftui/loading-images/3292) but there are many different solutions online – cedricbahirwe Jul 20 '21 at 18:10
  • To learn more about `Image` (https://developer.apple.com/documentation/swiftui/image) – cedricbahirwe Jul 20 '21 at 18:12