Home > database >  Calling a web API via Swift
Calling a web API via Swift

Time:12-23

I have ran into an issue with this, I am not sure what I am doing wrong for nothing to be displaying. I am pretty positive I am doing this correctly (well I guess I'm not) but I cannot figure out what I am doing wrong. I am new to Swift so I am learning still which is why I am taking it from this approach as I want to do this in the most simple way possible. So my question is, what part of this am I doing wrong?

SwiftUI Code:

//
//  ContentView.swift
//  APIExample

import SwiftUI
struct Response: Codable {
    var articles: [Article]
}

struct Article: Codable, Identifiable {
    var id = UUID()
    var author: String
    var title: String
}

struct ContentView: View {
    @State private var articles = [Article]()
    func loadData() async {
        guard let url = URL(string: "https://newsapi.org/v2/top-headlines?sources=techcrunch&apiKey=APIKEY") else {
            print("Invalid URL")
            return
        }
        do {
            let (data, _) = try await URLSession.shared.data(from: url)

            if let decodedResponse = try? JSONDecoder().decode(Response.self, from: data) {
                articles = decodedResponse.articles
            }
        } catch {
            print("Invalid data")
        }
    }
    var body: some View {
        List(articles, id: \.id) { item in
            VStack(alignment: .leading) {
                Text(item.author)
                    .font(.headline)
                Text(item.title)
            }
        }.task {
            await loadData()
        }
    }
}

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

JSON: https://pastebin.com/Zn4kY2BV

CodePudding user response:

The error you get is:

Invalid data: keyNotFound(CodingKeys(stringValue: "id", intValue: nil), Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "articles", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "No value associated with key CodingKeys(stringValue: \"id\", intValue: nil) (\"id\").", underlyingError: nil))

you could fix the error by supplying a custom decode init

struct Article: Codable, Identifiable {
    var id = UUID()
    var author: String
    var title: String
  
  enum CodingKeys: CodingKey {
    case author
    case title
  }
  
  init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
    author = try container.decode(String.self, forKey: .author)
    title = try container.decode(String.self, forKey: .title)
  }
}

CodePudding user response:

id is in JSON, but not how you have specified it in your code:

struct Response: Codable {
    var articles: [Article]
}
struct Source: Codable {
    var id: String
    var name: String
}
struct Article: Codable, Identifiable {
    var source = Source
    var author: String
    var title: String

}

And for your ListView()

List(articles) { item in
        VStack(alignment: .leading) {
            Text(item.author)
                .font(.headline)
            Text(item.title)
        }
}
  • Related